Welcome to the KAT Communication Protocol’s documentation!¶
KATCP is a simple ASCII communication protocol layered on top of TCP/IP.
It is developed as a part of the Karoo Array Telescope (KAT) project and used at KAT for the monitoring and control of hardware devices.
The protocol specification NRF-KAT7-6.0-IFCE-002-Rev5-1.pdf
is maintained as an internal memo. The latest version is Rev5.1.
The specification source is hosted here: https://github.com/ska-sa/katcp-guidelines
Contents¶
Release Notes¶
0.9.0¶
- Add asyncio compatible ioloop to ioloop manager.
0.8.0¶
- Added bulk sensor sampling feature.
0.7.2¶
- Support for handling generator expressions in
Discrete
type. - Fix handling of strings and bytes in
get_sensor
in testutils. - Allow strings or bytes for
assert_request_fails
andtest_assert_request_succeeds
function arguments. - Handle
str
type correctly (‘easier’) intestutils.get_sensor
for python 2 and python 3. - Allow bytes and strings in
test_sensor_list
comparison of sensors. - Correct handling of floats
test_sensor_list
. - black formatting on certain test files.
0.7.1¶
- All params in
future_get_sensor
are now cast to byte strings. - Added tests to
test_fake_clients.py
andtest_inspecting_client.py
. - Ensure
testutils
method casts expected requests to byte strings.
0.7.0¶
- Added Python 3 compatibility.
See also CHANGELOG.md
for more details on changes.
Important changes for Python 3 compatibility¶
General notes¶
The package is now compatible with both Python 2 and 3. The goals of the migration were:
- Do not change the public API.
- Do not break existing functionality for Python 2.
- Ease migration of packages using katcp to Python 3.
Despite these goals, some of the stricter type checking that has been added may force minor updates in existing code. E.g., using integer for the options of a discrete sensor is no longer allowed.
Asynchronous code is still using tornado in the same Python 2 way. The new
Python 3.5 async
and await
keywords are not used. The tornado version
is also pinned to older versions that support both Python 2 and 3. The 5.x
versions also support Python 2, but they are avoided as some significant
changes result in test failures.
The Python future
package was used for the compatibility layer. The use of
the newstr
and newbytes
compatibility types was avoided, to reduce
confusion. I.e., from builtins import str, bytes
is not done.
Docstrings¶
In docstrings the interpretation of parameter and return types described
as “str” has changed slightly. In Python 2 the str
type is a byte
string, while in Python 3, str
is a unicode string. The str
type
is referred to as the “native” string type. In code, native literal strings
would have no prefix, for example: "native string"
, as opposed to
explicit byte strings, b"byte string"
, and explicit unicode strings,
u"unicode string"
. In the docstrings “bytes” means a byte string is
expected (or returned), “str” means a native string, and “str or bytes”
means either type.
Changes to types¶
As part of the Python 3 compatibility update, note the following:
katcp.Message
. -arguments
andmid
attributes will be forced to byte strings in all Python versions. This is to match what is sent on the wire (serialised byte stream). -name
: is expected to be a native string. -repr()
: the result will differ slightly in Python 3 - the arguments will be shown as quoted byte strings. E.g., Python 2:"<Message reply ok (123, zzz)>"
, vs. Python 3:"<Message reply ok (b'123', b'zzz')>"
. In all versions, arguments longer than 1000 characters are now truncated.katcp.Sensor
. -name
,description
,units
,params
(for discrete sensors):__init__
can take byte strings or native strings, but attributes will be coerced to native strings. -set_formatted
,parse_value
: only accept byte strings (stricter checking). - Thefloat
andstrict_timestamp
sensor values are now encoded usingrepr()
instead of"%.15g"
. This means that more significant digits are transmitted on the wire (16 to 17, instead of 15), and the client will be able to reconstruct the exact some floating point value.
Non-ASCII and UTF-8¶
Prior to these changes, all strings were byte strings, so there was no encoding
required. Arbitrary bytes could be used for message parameters and string
sensor values. After these changes, strings sensors and Str
types are
considered “text”. In Python 3, UTF-8 encoding will be used when changing
between byte strings and unicode strings for “text”. This has the following
effects:
katcp.Message
- thearguments
are always using byte strings, so arbitrary bytes can still be sent and received using this class directly.katcp.Sensor
- Values forstring
anddiscrete
sensor types cannot be arbitrary byte strings in Python 3 - they need to be UTF-8 compatible.kattypes.Str
,kattypes.Discrete
,kattypes.DiscreteMulti
- These types is still used inrequest
andreply
decorators. - For sending messages, they accept any type of object, but UTF-8 encoding is used if values are not already byte strings. - When decoding received messages, “native” strings are returned.
Keep in mind that a Python 2 server may be communicating with a Python 3 client, so sticking to ASCII is safest. If you are sure both client and server are on Python 3 (or understand the encoding the same), then UTF-8 could be used. That is also the encoding option used by the aiokatcp package.
Performance degradation¶
Adding the compatibility results in more checks and conversions. From some basic benchmarking, there appears to be up to 20% performance degradation when instantiating message objects.
Benchmark, in ipython:
import random, katcp
args_groups = []
for i in range(1000):
args_groups.append((random.randint(0, 1) == 1,
random.randint(0, 1000),
random.random(),
str(random.random())))
def benchmark():
for args in args_groups:
tx_msg = katcp.Message.reply('foo', *args)
serialised = bytes(tx_msg)
parser = katcp.MessageParser()
rx_msg = parser.parse(serialised)
assert tx_msg == rx_msg
%timeit benchmark()
- Old Py2: 10 loops, best of 3: 23.4 ms per loop
- New Py2: 10 loops, best of 3: 29.9 ms per loop
- New Py3: 25.1 ms ± 86.8 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
0.6.4¶
- Fix some client memory leaks, and add until_stopped methods.
- Increase server MAX_QUEUE_SIZE to handle more clients.
- Use correct ioloop for client AsyncEvent objects.
See also CHANGELOG.md
for more details on changes.
Important API changes¶
Stopping KATCP clients¶
When stopping KATCP client classes that use a managed ioloop (i.e., create their
own in a new thread), the traditional semantics are to call stop()
followed by
join()
from another thread. This is unchanged. In the case of an unmanaged
ioloop (i.e., an existing ioloop instance is provided to the client), we typically
stop from the same thread, and calling join()
does nothing. For the case of
unmanaged ioloops, a new method, until_stopped()
, has been added. It returns a
future that resolves when the client has stopped. The caller can yield
on this
future to be sure that the client has completed all its coroutines. Using this new
method is not required. If the ioloop will keep running, the stopped client’s
coroutines will eventually exit. However, it is useful in some cases, e.g., to
verify correct clean up in unit tests.
The new method is available on katcp.DeviceClient
and derived classes, on
katcp.inspecting_client.InspectingClientAsync
, and on the high-level
clients katcp.KATCPClientResource
and
katcp.KATCPClientResourceContainer
.
An additional change is that the inspecting client now sends a state update
(indicating that it is disconnected and not synced) when stopping. This means
high-level clients that were waiting on until_not_synced
when the client was
stopped will now be notified. Previously, this was not the case.
0.6.3¶
- Put docs on readthedocs.
- Better error handling for messages with non-ASCII characters (invalid).
- Increase container sync time to better support large containers.
- Limit tornado version to <5.
- Allow sampling strategy to be removed from cache.
- Improve error messages for DeviceMetaClass assertions.
- Increase server’s message queue length handle more simultaneous client connections.
- Improve Jenkins pipeline configuration.
- Add information on how to contribute to the project.
See also CHANGELOG.md
for more details on changes.
0.6.2¶
- Various bug fixes
- Docstring and code style improvements
- Bumped the tornado dependency to at least 4.3
- Added the ability to let ClientGroup wait for a quorum of clients
- Added default request-timeout-hint implementation to server.py
- Moved IOLoopThreadWrapper to ioloop_manager.py, a more sensible location
- Added a random-exponential retry backoff process
See also CHANGELOG.md
for more details on changes.
0.6.1¶
- Various bug fixes
- Improvements to testing utilities
- Improvements to various docstrings
- Use katversion to determine version string on install
- Better dependency management using setup.py with setuptools
- Fixed a memory leak when using KATCPResourceContainer
See also CHANGELOG.md
for more details on changes.
0.6.0¶
- Major change: Use the tornado event loop and async socket routines.
See also CHANGELOG.md
for more details on changes.
Important API changes¶
Tornado based event loop(s)¶
While the networking stack and event loops have been re-implemented using
Tornado, this change should be largely invisible to existing users of the
library. All client and server classes now expose an ioloop attribute that is
the tornado.ioloop.IOLoop
instance being used. Unless new server or
client classes are used or default settings are changed, the thread-safety and
concurrency semantics of 0.5.x versions should be retained. User code that made
use of non-public interfaces may run into trouble.
High level auto-inspecting KATCP client APIs added¶
The high level client API inspects a KATCP device server and present requests as method calls and sensors as objects. See Using the high-level client API.
Sensor observer API¶
The katcp.Sensor
sensor observer API has been changed to pass the
sensor reading in the observer.update() callback, preventing potential lost
updates due to race conditions. This is a backwards incompatible change.
Whereas before observers were called as observer.update(sensor), they are now
called as observer.update(sensor, reading), where reading is an instance of
katcp.core.Reading
.
Sample Strategy callback API¶
Sensor strategies now call back with the sensor object and raw Python datatype
values rather than the sensor name and KATCP formatted values. The sensor
classes have also grown a katcp.Sensor.format_reading()
method that
can be used to do KATCP-version specific formatting of the sensor reading.
0.5.5¶
- Various cleanups (logging, docstrings, base request set, minor refactoring)
- Improvements to testing utilities
- Convenience utility functions in katcp.version, katcp.client, katcp.testutils.
0.5.4¶
- Change event-rate strategy to always send an update if the sensor has changed and shortest-period has passed.
- Add differential-rate strategy.
0.5.3¶
Add convert_seconds()
method to katcp client classes that converts seconds
into the device timestamp format.
0.5.2¶
Fix memory leak in sample reactor, other minor fixes.
0.5.1¶
Minor bugfixes and stability improvements
0.5.0¶
First stable release supporting (a subset of) KATCP v5. No updates apart from documentation since 0.5.0a0; please refer to the 0.5.0a release notes below.
0.5.0a0¶
First alpha release supporting (a subset of) KATCP v5. The KATCP v5 spec brings a number of backward incompatible changes, and hence requires care. This library implements support for both KATCP v5 and for the older dialect. Some API changes have also been made, mainly in aid of fool-proof support of the Message ID feature of KATCP v5. The changes do, however, also eliminate a category of potential bugs for older versions of the spec.
Important API changes¶
CallbackClient.request()¶
Renamed request()
to callback_request()
to be more consistent with superclass
API.
Sending replies and informs in server request handlers¶
The function signature used for request handler methods in previous versions of
this library were request_requestname(self, sock, msg), where sock is a
raw python socket object and msg is a katcp Message
object. The sock
object was never used directly by the request handler, but was passed to methods
on the server to send inform or reply messages.
Before:
class MyServer(DeviceServer):
def request_echo(self, sock, msg):
self.inform(sock, Message.inform('echo', len(msg.arguments)))
return Message.reply('echo', 'ok', *msg.arguments)
The old method requires the name of the request to be repeated several times,
inviting error and cluttering code. The user is also required to instantiate
katcp Message
object each time a reply is made. The new method passes a
request-bound connection object that knows to what request it is replying, and
that automatically constructs Message
objects.
Now:
class MyServer(DeviceServer):
def request_echo(self, req, msg):
req.inform(len(msg.arguments)))
return req.make_reply('ok', *msg.arguments)
A req.reply()
method with the same signature as req.make_reply()
is also available for asyncronous reply handlers, and
req.reply_with_message()
which takes a Message
instance rather
than message arguments. These methods replace the use of
DeviceServer.reply()
.
The request object also contains the katcp request Message
object
(req.msg), and the equivalent of a socket object
(req.client_connection). See the next section for a description of
client_connection.
Using the server methods with a req object in place of sock will still work as before, but will log deprecation warnings.
Connection abstraction¶
Previously, the server classes internally used each connection’s low-level
sock object as an identifier for the connection. In the interest of
abstracting out the transport backend, the sock object has been replaced by a
ClientConnectionTCP
object. This object is passed to all server handler
functions (apart from request handlers) instead of the sock object. The
connection object be used in the same places where sock was previously
used. It also defines inform()
, reply_inform()
and reply()
methods for sending Message
objects to a client.
Backwards incompatible KATCP V5 changes¶
Timestamps¶
Excerpted from NRF-KAT7-6.0-IFCE-002-Rev5.pdf
:
All core messages involving time (i.e. timestamp or period specifications) have changed from using milliseconds to seconds. This provides consistency with SI units. Note also that from version five timestamps should always be specified in UTC time.
Message Identifiers (mid)¶
Excerpted from NRF-KAT7-6.0-IFCE-002-Rev5.pdf
:
Message identifiers were introduced in version 5 of the protocol to allow replies to be uniquely associated with a particular request. If a client sends a request with a message identifier the server must include the same identifier in the reply. Message identifiers are limited to integers in the range 1 to 231 − 1 inclusive. It is the client’s job to construct suitable identifiers – a server should not assume that these are unique. Clients that need to determine whether a server supports message identifiers should examine the #version-connect message returned by the server when the client connects (see Section 4). If no #version-connect message is received the client may assume message identifiers are not supported.
also:
If the request contained a message id each inform that forms part of the response should be marked with the original message id.
Support for message IDs is optional. A properly implemented server should never use mids in replies unless the client request has an mid. Similarly, a client should be able to detect whether a server supports MIDs by checking the #version-connect informs sent by the server, or by doing a !version-list request. Furthermore, a KATCP v5 server should never send #build-state or #version informs.
Server KATCP Version Auto-detection¶
The DeviceClient
client uses the presence of
#build-state or #version informs as a heuristic to detect pre-v5 servers,
and the presence of #version-connect informs to detect v5+ servers. If mixed
messages are received the client gives up auto-detection and disconnects. In
this case preset_protocol_flags()
can be used to
configure the client before calling start()
.
Level of KATCP support in this release¶
This release implements the majority of the KATCP v5 spec; excluded parts are:
- Support for optional warning/error range meta-information on sensors.
- Differential-rate sensor strategy.
Core API¶
Client¶
Two different clients are provided: the BlockingClient
for synchronous communication with a server and the CallbackClient
for asynchronous communication. Both clients raise KatcpClientError
when exceptions occur.
The DeviceClient
base class is provided as a foundation for
those wishing to implement their own clients.
BlockingClient¶
-
class
katcp.
BlockingClient
(host, port, tb_limit=20, timeout=5.0, logger=<logging.Logger object>, auto_reconnect=True)¶ Methods
BlockingClient.blocking_request
(msg[, …])Send a request message and wait for its reply. BlockingClient.callback_request
(msg[, …])Send a request message. BlockingClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. BlockingClient.disconnect
()Force client connection to close, reconnect if auto-connect set. BlockingClient.enable_thread_safety
()Enable thread-safety features. BlockingClient.future_request
(msg[, …])Send a request message, with future replies. BlockingClient.handle_inform
(msg)Handle inform messages related to any current requests. BlockingClient.handle_message
(msg)Handle a message from the server. BlockingClient.handle_reply
(msg)Handle a reply message related to the current request. BlockingClient.handle_request
(msg)Dispatch a request message to the appropriate method. BlockingClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. BlockingClient.inform_version
(msg)Handle katcp v4 and below version inform. BlockingClient.inform_version_connect
(msg)Process a #version-connect message. BlockingClient.is_connected
()Check if the socket is currently connected. BlockingClient.join
([timeout])Rejoin the client thread. BlockingClient.next
()BlockingClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. BlockingClient.preset_protocol_flags
(…)Preset server protocol flags. BlockingClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. BlockingClient.running
()Whether the client is running. BlockingClient.send_message
(msg)Send any kind of message. BlockingClient.send_request
(msg)Send a request message. BlockingClient.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False BlockingClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. BlockingClient.start
([timeout])Start the client in a new thread. BlockingClient.stop
(*args, **kwargs)Stop a running client. BlockingClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. BlockingClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. BlockingClient.unhandled_request
(msg)Fallback method for requests without a registered handler. BlockingClient.until_connected
(**kwargs)Return future that resolves when the client is connected. BlockingClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. BlockingClient.until_running
([timeout])Return future that resolves when the client is running. BlockingClient.until_stopped
([timeout])Return future that resolves when the client has stopped. BlockingClient.wait_connected
([timeout])Wait until the client is connected. BlockingClient.wait_disconnected
([timeout])Wait until the client is disconnected. BlockingClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. BlockingClient.wait_running
([timeout])Wait until the client is running. -
bind_address
¶ (host, port) where the client is connecting
-
blocking_request
(msg, timeout=None, use_mid=None)¶ Send a request message and wait for its reply.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
callback_request
(msg, reply_cb=None, inform_cb=None, user_data=None, timeout=None, use_mid=None)¶ Send a request message.
Parameters: msg : Message object
The request message to send.
reply_cb : function
The reply callback with signature reply_cb(msg) or reply_cb(msg, *user_data)
inform_cb : function
The inform callback with signature inform_cb(msg) or inform_cb(msg, *user_data)
user_data : tuple
Optional user data to send to the reply and inform callbacks.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
-
convert_seconds
(time_seconds)¶ Convert a time in seconds to the device timestamp units.
KATCP v4 and earlier, specified all timestamps in milliseconds. Since KATCP v5, all timestamps are in seconds. If the device KATCP version has been detected, this method converts a value in seconds to the appropriate (seconds or milliseconds) quantity. For version smaller than V4, the time value will be truncated to the nearest millisecond.
-
disconnect
()¶ Force client connection to close, reconnect if auto-connect set.
-
enable_thread_safety
()¶ Enable thread-safety features.
Must be called before start().
-
future_request
(msg, timeout=None, use_mid=None)¶ Send a request message, with future replies.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: A tornado.concurrent.Future that resolves with: :
reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
handle_inform
(msg)¶ Handle inform messages related to any current requests.
Inform messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The inform message to dispatch.
-
handle_message
(msg)¶ Handle a message from the server.
Parameters: msg : Message object
The Message to dispatch to the handler methods.
-
handle_reply
(msg)¶ Handle a reply message related to the current request.
Reply messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The reply message to dispatch.
-
handle_request
(msg)¶ Dispatch a request message to the appropriate method.
Parameters: msg : Message object
The request message to dispatch.
-
inform_build_state
(msg)¶ Handle katcp v4 and below build-state inform.
-
inform_version
(msg)¶ Handle katcp v4 and below version inform.
-
inform_version_connect
(msg)¶ Process a #version-connect message.
-
is_connected
()¶ Check if the socket is currently connected.
Returns: connected : bool
Whether the client is connected.
-
join
(timeout=None)¶ Rejoin the client thread.
Parameters: timeout : float in seconds
Seconds to wait for thread to finish.
Notes
Does nothing if the ioloop is not managed. Use until_stopped() instead.
-
notify_connected
(connected)¶ Event handler that is called whenever the connection status changes.
Override in derived class for desired behaviour.
Note
This function should never block. Doing so will cause the client to cease processing data from the server until notify_connected completes.
Parameters: connected : bool
Whether the client has just connected (True) or just disconnected (False).
-
preset_protocol_flags
(protocol_flags)¶ Preset server protocol flags.
Sets the assumed server protocol flags and disables automatic server version detection.
Parameters: protocol_flags : katcp.core.ProtocolFlags instance
-
request
(msg, use_mid=None)¶ Send a request message, with automatic message ID assignment.
Parameters: msg : katcp.Message request message
use_mid : bool or None, default=None
Returns: mid : string or None
The message id, or None if no msg id is used
If use_mid is None and the server supports msg ids, or if use_mid is :
True a message ID will automatically be assigned msg.mid is None. :
if msg.mid has a value, and the server supports msg ids, that value :
will be used. If the server does not support msg ids, KatcpVersionError :
will be raised. :
-
running
()¶ Whether the client is running.
Returns: running : bool
Whether the client is running.
-
send_message
(msg)¶ Send any kind of message.
Parameters: msg : Message object
The message to send.
-
send_request
(msg)¶ Send a request message.
Parameters: msg : Message object
The request Message to send.
-
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
set_ioloop
(ioloop=None)¶ Set the tornado.ioloop.IOLoop instance to use.
This defaults to IOLoop.current(). If set_ioloop() is never called the IOLoop is managed: started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called
-
start
(timeout=None)¶ Start the client in a new thread.
Parameters: timeout : float in seconds
Seconds to wait for client thread to start. Do not specify a timeout if start() is being called from the same ioloop that this client will be installed on, since it will block the ioloop without progressing.
-
stop
(*args, **kwargs)¶ Stop a running client.
If using a managed ioloop, this must be called from a different thread to the ioloop’s. This method only returns once the client’s main coroutine, _install(), has completed.
If using an unmanaged ioloop, this can be called from the same thread as the ioloop. The until_stopped() method can be used to wait on completion of the main coroutine, _install().
Parameters: timeout : float in seconds
Seconds to wait for both client thread to have started, and for stopping.
-
unhandled_inform
(msg)¶ Fallback method for inform messages without a registered handler.
Parameters: msg : Message object
The inform message that wasn’t processed by any handlers.
-
unhandled_reply
(msg)¶ Fallback method for reply messages without a registered handler.
Parameters: msg : Message object
The reply message that wasn’t processed by any handlers.
-
unhandled_request
(msg)¶ Fallback method for requests without a registered handler.
Parameters: msg : Message object
The request message that wasn’t processed by any handlers.
-
until_connected
(**kwargs)¶ Return future that resolves when the client is connected.
-
until_protocol
(**kwargs)¶ Return future that resolves after receipt of katcp protocol info.
If the returned future resolves, the server’s protocol information is available in the ProtocolFlags instance self.protocol_flags.
-
until_running
(timeout=None)¶ Return future that resolves when the client is running.
Notes
Must be called from the same ioloop as the client.
-
until_stopped
(timeout=None)¶ Return future that resolves when the client has stopped.
Parameters: timeout : float in seconds
Seconds to wait for the client to stop.
Notes
If already running, stop() must be called before this.
Must be called from the same ioloop as the client. If using a different thread, or a managed ioloop, this method should not be used. Use join() instead.
Also note that stopped != not running. Stopped means the main coroutine has ended, or was never started. When stopping, the running flag is cleared some time before stopped is set.
-
wait_connected
(timeout=None)¶ Wait until the client is connected.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: connected : bool
Whether the client is connected.
Notes
Do not call this from the ioloop, use until_connected().
-
wait_disconnected
(timeout=None)¶ Wait until the client is disconnected.
Parameters: timeout : float in seconds
Seconds to wait for the client to disconnect.
Returns: disconnected : bool
Whether the client is disconnected.
Notes
Do not call this from the ioloop, use until_disconnected().
-
wait_protocol
(timeout=None)¶ Wait until katcp protocol information has been received from server.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: received : bool
Whether protocol information was received
If this method returns True, the server’s protocol information is :
available in the ProtocolFlags instance self.protocol_flags. :
Notes
Do not call this from the ioloop, use until_protocol().
-
wait_running
(timeout=None)¶ Wait until the client is running.
Parameters: timeout : float in seconds
Seconds to wait for the client to start running.
Returns: running : bool
Whether the client is running
Notes
Do not call this from the ioloop, use until_running().
-
CallbackClient¶
-
class
katcp.
CallbackClient
(host, port, tb_limit=20, timeout=5.0, logger=<logging.Logger object>, auto_reconnect=True)¶ Methods
CallbackClient.blocking_request
(msg[, …])Send a request message and wait for its reply. CallbackClient.callback_request
(msg[, …])Send a request message. CallbackClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. CallbackClient.disconnect
()Force client connection to close, reconnect if auto-connect set. CallbackClient.enable_thread_safety
()Enable thread-safety features. CallbackClient.future_request
(msg[, …])Send a request message, with future replies. CallbackClient.handle_inform
(msg)Handle inform messages related to any current requests. CallbackClient.handle_message
(msg)Handle a message from the server. CallbackClient.handle_reply
(msg)Handle a reply message related to the current request. CallbackClient.handle_request
(msg)Dispatch a request message to the appropriate method. CallbackClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. CallbackClient.inform_version
(msg)Handle katcp v4 and below version inform. CallbackClient.inform_version_connect
(msg)Process a #version-connect message. CallbackClient.is_connected
()Check if the socket is currently connected. CallbackClient.join
([timeout])Rejoin the client thread. CallbackClient.next
()CallbackClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. CallbackClient.preset_protocol_flags
(…)Preset server protocol flags. CallbackClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. CallbackClient.running
()Whether the client is running. CallbackClient.send_message
(msg)Send any kind of message. CallbackClient.send_request
(msg)Send a request message. CallbackClient.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False CallbackClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. CallbackClient.start
([timeout])Start the client in a new thread. CallbackClient.stop
(*args, **kwargs)Stop a running client. CallbackClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. CallbackClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. CallbackClient.unhandled_request
(msg)Fallback method for requests without a registered handler. CallbackClient.until_connected
(**kwargs)Return future that resolves when the client is connected. CallbackClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. CallbackClient.until_running
([timeout])Return future that resolves when the client is running. CallbackClient.until_stopped
([timeout])Return future that resolves when the client has stopped. CallbackClient.wait_connected
([timeout])Wait until the client is connected. CallbackClient.wait_disconnected
([timeout])Wait until the client is disconnected. CallbackClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. CallbackClient.wait_running
([timeout])Wait until the client is running. -
bind_address
¶ (host, port) where the client is connecting
-
blocking_request
(msg, timeout=None, use_mid=None)¶ Send a request message and wait for its reply.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
callback_request
(msg, reply_cb=None, inform_cb=None, user_data=None, timeout=None, use_mid=None)¶ Send a request message.
Parameters: msg : Message object
The request message to send.
reply_cb : function
The reply callback with signature reply_cb(msg) or reply_cb(msg, *user_data)
inform_cb : function
The inform callback with signature inform_cb(msg) or inform_cb(msg, *user_data)
user_data : tuple
Optional user data to send to the reply and inform callbacks.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
-
convert_seconds
(time_seconds)¶ Convert a time in seconds to the device timestamp units.
KATCP v4 and earlier, specified all timestamps in milliseconds. Since KATCP v5, all timestamps are in seconds. If the device KATCP version has been detected, this method converts a value in seconds to the appropriate (seconds or milliseconds) quantity. For version smaller than V4, the time value will be truncated to the nearest millisecond.
-
disconnect
()¶ Force client connection to close, reconnect if auto-connect set.
-
enable_thread_safety
()¶ Enable thread-safety features.
Must be called before start().
-
future_request
(msg, timeout=None, use_mid=None)¶ Send a request message, with future replies.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: A tornado.concurrent.Future that resolves with: :
reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
handle_inform
(msg)¶ Handle inform messages related to any current requests.
Inform messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The inform message to dispatch.
-
handle_message
(msg)¶ Handle a message from the server.
Parameters: msg : Message object
The Message to dispatch to the handler methods.
-
handle_reply
(msg)¶ Handle a reply message related to the current request.
Reply messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The reply message to dispatch.
-
handle_request
(msg)¶ Dispatch a request message to the appropriate method.
Parameters: msg : Message object
The request message to dispatch.
-
inform_build_state
(msg)¶ Handle katcp v4 and below build-state inform.
-
inform_version
(msg)¶ Handle katcp v4 and below version inform.
-
inform_version_connect
(msg)¶ Process a #version-connect message.
-
is_connected
()¶ Check if the socket is currently connected.
Returns: connected : bool
Whether the client is connected.
-
join
(timeout=None)¶ Rejoin the client thread.
Parameters: timeout : float in seconds
Seconds to wait for thread to finish.
Notes
Does nothing if the ioloop is not managed. Use until_stopped() instead.
-
notify_connected
(connected)¶ Event handler that is called whenever the connection status changes.
Override in derived class for desired behaviour.
Note
This function should never block. Doing so will cause the client to cease processing data from the server until notify_connected completes.
Parameters: connected : bool
Whether the client has just connected (True) or just disconnected (False).
-
preset_protocol_flags
(protocol_flags)¶ Preset server protocol flags.
Sets the assumed server protocol flags and disables automatic server version detection.
Parameters: protocol_flags : katcp.core.ProtocolFlags instance
-
request
(msg, use_mid=None)¶ Send a request message, with automatic message ID assignment.
Parameters: msg : katcp.Message request message
use_mid : bool or None, default=None
Returns: mid : string or None
The message id, or None if no msg id is used
If use_mid is None and the server supports msg ids, or if use_mid is :
True a message ID will automatically be assigned msg.mid is None. :
if msg.mid has a value, and the server supports msg ids, that value :
will be used. If the server does not support msg ids, KatcpVersionError :
will be raised. :
-
running
()¶ Whether the client is running.
Returns: running : bool
Whether the client is running.
-
send_message
(msg)¶ Send any kind of message.
Parameters: msg : Message object
The message to send.
-
send_request
(msg)¶ Send a request message.
Parameters: msg : Message object
The request Message to send.
-
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
set_ioloop
(ioloop=None)¶ Set the tornado.ioloop.IOLoop instance to use.
This defaults to IOLoop.current(). If set_ioloop() is never called the IOLoop is managed: started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called
-
start
(timeout=None)¶ Start the client in a new thread.
Parameters: timeout : float in seconds
Seconds to wait for client thread to start. Do not specify a timeout if start() is being called from the same ioloop that this client will be installed on, since it will block the ioloop without progressing.
-
stop
(*args, **kwargs)¶ Stop a running client.
If using a managed ioloop, this must be called from a different thread to the ioloop’s. This method only returns once the client’s main coroutine, _install(), has completed.
If using an unmanaged ioloop, this can be called from the same thread as the ioloop. The until_stopped() method can be used to wait on completion of the main coroutine, _install().
Parameters: timeout : float in seconds
Seconds to wait for both client thread to have started, and for stopping.
-
unhandled_inform
(msg)¶ Fallback method for inform messages without a registered handler.
Parameters: msg : Message object
The inform message that wasn’t processed by any handlers.
-
unhandled_reply
(msg)¶ Fallback method for reply messages without a registered handler.
Parameters: msg : Message object
The reply message that wasn’t processed by any handlers.
-
unhandled_request
(msg)¶ Fallback method for requests without a registered handler.
Parameters: msg : Message object
The request message that wasn’t processed by any handlers.
-
until_connected
(**kwargs)¶ Return future that resolves when the client is connected.
-
until_protocol
(**kwargs)¶ Return future that resolves after receipt of katcp protocol info.
If the returned future resolves, the server’s protocol information is available in the ProtocolFlags instance self.protocol_flags.
-
until_running
(timeout=None)¶ Return future that resolves when the client is running.
Notes
Must be called from the same ioloop as the client.
-
until_stopped
(timeout=None)¶ Return future that resolves when the client has stopped.
Parameters: timeout : float in seconds
Seconds to wait for the client to stop.
Notes
If already running, stop() must be called before this.
Must be called from the same ioloop as the client. If using a different thread, or a managed ioloop, this method should not be used. Use join() instead.
Also note that stopped != not running. Stopped means the main coroutine has ended, or was never started. When stopping, the running flag is cleared some time before stopped is set.
-
wait_connected
(timeout=None)¶ Wait until the client is connected.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: connected : bool
Whether the client is connected.
Notes
Do not call this from the ioloop, use until_connected().
-
wait_disconnected
(timeout=None)¶ Wait until the client is disconnected.
Parameters: timeout : float in seconds
Seconds to wait for the client to disconnect.
Returns: disconnected : bool
Whether the client is disconnected.
Notes
Do not call this from the ioloop, use until_disconnected().
-
wait_protocol
(timeout=None)¶ Wait until katcp protocol information has been received from server.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: received : bool
Whether protocol information was received
If this method returns True, the server’s protocol information is :
available in the ProtocolFlags instance self.protocol_flags. :
Notes
Do not call this from the ioloop, use until_protocol().
-
wait_running
(timeout=None)¶ Wait until the client is running.
Parameters: timeout : float in seconds
Seconds to wait for the client to start running.
Returns: running : bool
Whether the client is running
Notes
Do not call this from the ioloop, use until_running().
-
AsyncClient¶
-
class
katcp.
AsyncClient
(host, port, tb_limit=20, timeout=5.0, logger=<logging.Logger object>, auto_reconnect=True)¶ Implement async and callback-based requests on top of DeviceClient.
This client will use message IDs if the server supports them.
Parameters: host : string
Host to connect to.
port : int
Port to connect to.
tb_limit : int, optional
Maximum number of stack frames to send in error traceback.
logger : object, optional
Python Logger object to log to. Default is a logger named ‘katcp’.
auto_reconnect : bool, optional
Whether to automatically reconnect if the connection dies.
timeout : float in seconds, optional
Default number of seconds to wait before a callback callback_request times out. Can be overridden in individual calls to callback_request.
Examples
>>> def reply_cb(msg): ... print "Reply:", msg ... >>> def inform_cb(msg): ... print "Inform:", msg ... >>> c = AsyncClient('localhost', 10000) >>> c.start() >>> c.ioloop.add_callback( ... c.callback_request, ... katcp.Message.request('myreq'), ... reply_cb=reply_cb, ... inform_cb=inform_cb, ... ) ... >>> # expect reply to be printed here >>> # stop the client once we're finished with it >>> c.stop() >>> c.join()
Methods
AsyncClient.blocking_request
(msg[, timeout, …])Send a request message and wait for its reply. AsyncClient.callback_request
(msg[, …])Send a request message. AsyncClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. AsyncClient.disconnect
()Force client connection to close, reconnect if auto-connect set. AsyncClient.enable_thread_safety
()Enable thread-safety features. AsyncClient.future_request
(msg[, timeout, …])Send a request message, with future replies. AsyncClient.handle_inform
(msg)Handle inform messages related to any current requests. AsyncClient.handle_message
(msg)Handle a message from the server. AsyncClient.handle_reply
(msg)Handle a reply message related to the current request. AsyncClient.handle_request
(msg)Dispatch a request message to the appropriate method. AsyncClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. AsyncClient.inform_version
(msg)Handle katcp v4 and below version inform. AsyncClient.inform_version_connect
(msg)Process a #version-connect message. AsyncClient.is_connected
()Check if the socket is currently connected. AsyncClient.join
([timeout])Rejoin the client thread. AsyncClient.next
()AsyncClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. AsyncClient.preset_protocol_flags
(protocol_flags)Preset server protocol flags. AsyncClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. AsyncClient.running
()Whether the client is running. AsyncClient.send_message
(msg)Send any kind of message. AsyncClient.send_request
(msg)Send a request message. AsyncClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. AsyncClient.start
([timeout])Start the client in a new thread. AsyncClient.stop
(*args, **kwargs)Stop a running client. AsyncClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. AsyncClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. AsyncClient.unhandled_request
(msg)Fallback method for requests without a registered handler. AsyncClient.until_connected
(**kwargs)Return future that resolves when the client is connected. AsyncClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. AsyncClient.until_running
([timeout])Return future that resolves when the client is running. AsyncClient.until_stopped
([timeout])Return future that resolves when the client has stopped. AsyncClient.wait_connected
([timeout])Wait until the client is connected. AsyncClient.wait_disconnected
([timeout])Wait until the client is disconnected. AsyncClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. AsyncClient.wait_running
([timeout])Wait until the client is running. -
bind_address
¶ (host, port) where the client is connecting
-
blocking_request
(msg, timeout=None, use_mid=None)¶ Send a request message and wait for its reply.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
callback_request
(msg, reply_cb=None, inform_cb=None, user_data=None, timeout=None, use_mid=None)¶ Send a request message.
Parameters: msg : Message object
The request message to send.
reply_cb : function
The reply callback with signature reply_cb(msg) or reply_cb(msg, *user_data)
inform_cb : function
The inform callback with signature inform_cb(msg) or inform_cb(msg, *user_data)
user_data : tuple
Optional user data to send to the reply and inform callbacks.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
-
convert_seconds
(time_seconds)¶ Convert a time in seconds to the device timestamp units.
KATCP v4 and earlier, specified all timestamps in milliseconds. Since KATCP v5, all timestamps are in seconds. If the device KATCP version has been detected, this method converts a value in seconds to the appropriate (seconds or milliseconds) quantity. For version smaller than V4, the time value will be truncated to the nearest millisecond.
-
disconnect
()¶ Force client connection to close, reconnect if auto-connect set.
-
enable_thread_safety
()¶ Enable thread-safety features.
Must be called before start().
-
future_request
(msg, timeout=None, use_mid=None)¶ Send a request message, with future replies.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: A tornado.concurrent.Future that resolves with: :
reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
handle_inform
(msg)¶ Handle inform messages related to any current requests.
Inform messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The inform message to dispatch.
-
handle_message
(msg)¶ Handle a message from the server.
Parameters: msg : Message object
The Message to dispatch to the handler methods.
-
handle_reply
(msg)¶ Handle a reply message related to the current request.
Reply messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The reply message to dispatch.
-
handle_request
(msg)¶ Dispatch a request message to the appropriate method.
Parameters: msg : Message object
The request message to dispatch.
-
inform_build_state
(msg)¶ Handle katcp v4 and below build-state inform.
-
inform_version
(msg)¶ Handle katcp v4 and below version inform.
-
inform_version_connect
(msg)¶ Process a #version-connect message.
-
is_connected
()¶ Check if the socket is currently connected.
Returns: connected : bool
Whether the client is connected.
-
join
(timeout=None)¶ Rejoin the client thread.
Parameters: timeout : float in seconds
Seconds to wait for thread to finish.
Notes
Does nothing if the ioloop is not managed. Use until_stopped() instead.
-
notify_connected
(connected)¶ Event handler that is called whenever the connection status changes.
Override in derived class for desired behaviour.
Note
This function should never block. Doing so will cause the client to cease processing data from the server until notify_connected completes.
Parameters: connected : bool
Whether the client has just connected (True) or just disconnected (False).
-
preset_protocol_flags
(protocol_flags)¶ Preset server protocol flags.
Sets the assumed server protocol flags and disables automatic server version detection.
Parameters: protocol_flags : katcp.core.ProtocolFlags instance
-
request
(msg, use_mid=None)¶ Send a request message, with automatic message ID assignment.
Parameters: msg : katcp.Message request message
use_mid : bool or None, default=None
Returns: mid : string or None
The message id, or None if no msg id is used
If use_mid is None and the server supports msg ids, or if use_mid is :
True a message ID will automatically be assigned msg.mid is None. :
if msg.mid has a value, and the server supports msg ids, that value :
will be used. If the server does not support msg ids, KatcpVersionError :
will be raised. :
-
running
()¶ Whether the client is running.
Returns: running : bool
Whether the client is running.
-
send_message
(msg)¶ Send any kind of message.
Parameters: msg : Message object
The message to send.
-
send_request
(msg)¶ Send a request message.
Parameters: msg : Message object
The request Message to send.
-
set_ioloop
(ioloop=None)¶ Set the tornado.ioloop.IOLoop instance to use.
This defaults to IOLoop.current(). If set_ioloop() is never called the IOLoop is managed: started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called
-
start
(timeout=None)¶ Start the client in a new thread.
Parameters: timeout : float in seconds
Seconds to wait for client thread to start. Do not specify a timeout if start() is being called from the same ioloop that this client will be installed on, since it will block the ioloop without progressing.
-
stop
(*args, **kwargs)¶ Stop a running client.
If using a managed ioloop, this must be called from a different thread to the ioloop’s. This method only returns once the client’s main coroutine, _install(), has completed.
If using an unmanaged ioloop, this can be called from the same thread as the ioloop. The until_stopped() method can be used to wait on completion of the main coroutine, _install().
Parameters: timeout : float in seconds
Seconds to wait for both client thread to have started, and for stopping.
-
unhandled_inform
(msg)¶ Fallback method for inform messages without a registered handler.
Parameters: msg : Message object
The inform message that wasn’t processed by any handlers.
-
unhandled_reply
(msg)¶ Fallback method for reply messages without a registered handler.
Parameters: msg : Message object
The reply message that wasn’t processed by any handlers.
-
unhandled_request
(msg)¶ Fallback method for requests without a registered handler.
Parameters: msg : Message object
The request message that wasn’t processed by any handlers.
-
until_connected
(**kwargs)¶ Return future that resolves when the client is connected.
-
until_protocol
(**kwargs)¶ Return future that resolves after receipt of katcp protocol info.
If the returned future resolves, the server’s protocol information is available in the ProtocolFlags instance self.protocol_flags.
-
until_running
(timeout=None)¶ Return future that resolves when the client is running.
Notes
Must be called from the same ioloop as the client.
-
until_stopped
(timeout=None)¶ Return future that resolves when the client has stopped.
Parameters: timeout : float in seconds
Seconds to wait for the client to stop.
Notes
If already running, stop() must be called before this.
Must be called from the same ioloop as the client. If using a different thread, or a managed ioloop, this method should not be used. Use join() instead.
Also note that stopped != not running. Stopped means the main coroutine has ended, or was never started. When stopping, the running flag is cleared some time before stopped is set.
-
wait_connected
(timeout=None)¶ Wait until the client is connected.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: connected : bool
Whether the client is connected.
Notes
Do not call this from the ioloop, use until_connected().
-
wait_disconnected
(timeout=None)¶ Wait until the client is disconnected.
Parameters: timeout : float in seconds
Seconds to wait for the client to disconnect.
Returns: disconnected : bool
Whether the client is disconnected.
Notes
Do not call this from the ioloop, use until_disconnected().
-
wait_protocol
(timeout=None)¶ Wait until katcp protocol information has been received from server.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: received : bool
Whether protocol information was received
If this method returns True, the server’s protocol information is :
available in the ProtocolFlags instance self.protocol_flags. :
Notes
Do not call this from the ioloop, use until_protocol().
-
wait_running
(timeout=None)¶ Wait until the client is running.
Parameters: timeout : float in seconds
Seconds to wait for the client to start running.
Returns: running : bool
Whether the client is running
Notes
Do not call this from the ioloop, use until_running().
-
Base Classes¶
-
class
katcp.
DeviceClient
(host, port, tb_limit=20, logger=<logging.Logger object>, auto_reconnect=True)¶ Device client proxy.
Subclasses should implement .reply_*, .inform_* and send_request_* methods to take actions when messages arrive, and implement unhandled_inform, unhandled_reply and unhandled_request to provide fallbacks for messages for which there is no handler.
Request messages can be sent by calling .send_request().
Parameters: host : string
Host to connect to.
port : int
Port to connect to.
tb_limit : int
Maximum number of stack frames to send in error traceback.
logger : object
Python Logger object to log to.
auto_reconnect : bool
Whether to automatically reconnect if the connection dies.
Notes
The client may block its ioloop if the default blocking tornado DNS resolver is used. When an ioloop is shared, it would make sense to configure one of the non-blocking resolver classes, see http://tornado.readthedocs.org/en/latest/netutil.html
Examples
>>> MyClient(DeviceClient): ... def reply_myreq(self, msg): ... print str(msg) ... >>> c = MyClient('localhost', 10000) >>> c.start() >>> c.send_request(katcp.Message.request('myreq')) >>> # expect reply to be printed here >>> # stop the client once we're finished with it >>> c.stop() >>> c.join()
Methods
DeviceClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. DeviceClient.disconnect
()Force client connection to close, reconnect if auto-connect set. DeviceClient.enable_thread_safety
()Enable thread-safety features. DeviceClient.handle_inform
(msg)Dispatch an inform message to the appropriate method. DeviceClient.handle_message
(msg)Handle a message from the server. DeviceClient.handle_reply
(msg)Dispatch a reply message to the appropriate method. DeviceClient.handle_request
(msg)Dispatch a request message to the appropriate method. DeviceClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. DeviceClient.inform_version
(msg)Handle katcp v4 and below version inform. DeviceClient.inform_version_connect
(msg)Process a #version-connect message. DeviceClient.is_connected
()Check if the socket is currently connected. DeviceClient.join
([timeout])Rejoin the client thread. DeviceClient.next
()DeviceClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. DeviceClient.preset_protocol_flags
(…)Preset server protocol flags. DeviceClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. DeviceClient.running
()Whether the client is running. DeviceClient.send_message
(msg)Send any kind of message. DeviceClient.send_request
(msg)Send a request message. DeviceClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. DeviceClient.start
([timeout])Start the client in a new thread. DeviceClient.stop
([timeout])Stop a running client. DeviceClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. DeviceClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. DeviceClient.unhandled_request
(msg)Fallback method for requests without a registered handler. DeviceClient.until_connected
(**kwargs)Return future that resolves when the client is connected. DeviceClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. DeviceClient.until_running
([timeout])Return future that resolves when the client is running. DeviceClient.until_stopped
([timeout])Return future that resolves when the client has stopped. DeviceClient.wait_connected
([timeout])Wait until the client is connected. DeviceClient.wait_disconnected
([timeout])Wait until the client is disconnected. DeviceClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. DeviceClient.wait_running
([timeout])Wait until the client is running. -
MAX_LOOP_LATENCY
= 0.03¶ Do not spend more than this many seconds reading pipelined socket data
IOStream inline-reading can result in ioloop starvation (see https://groups.google.com/forum/#!topic/python-tornado/yJrDAwDR_kA).
-
MAX_MSG_SIZE
= 2097152¶ Maximum message size that can be received in bytes.
If more than MAX_MSG_SIZE bytes are read from the socket without encountering a message terminator (i.e. newline), the connection is closed.
-
MAX_WRITE_BUFFER_SIZE
= 4194304¶ Maximum outstanding bytes to be buffered by the server process.
If more than MAX_WRITE_BUFFER_SIZE bytes are outstanding, the connection is closed. Note that the OS also buffers socket writes, so more than MAX_WRITE_BUFFER_SIZE bytes may be untransmitted in total.
-
bind_address
¶ (host, port) where the client is connecting
-
convert_seconds
(time_seconds)¶ Convert a time in seconds to the device timestamp units.
KATCP v4 and earlier, specified all timestamps in milliseconds. Since KATCP v5, all timestamps are in seconds. If the device KATCP version has been detected, this method converts a value in seconds to the appropriate (seconds or milliseconds) quantity. For version smaller than V4, the time value will be truncated to the nearest millisecond.
-
disconnect
()¶ Force client connection to close, reconnect if auto-connect set.
-
enable_thread_safety
()¶ Enable thread-safety features.
Must be called before start().
-
handle_inform
(msg)¶ Dispatch an inform message to the appropriate method.
Parameters: msg : Message object
The inform message to dispatch.
-
handle_message
(msg)¶ Handle a message from the server.
Parameters: msg : Message object
The Message to dispatch to the handler methods.
-
handle_reply
(msg)¶ Dispatch a reply message to the appropriate method.
Parameters: msg : Message object
The reply message to dispatch.
-
handle_request
(msg)¶ Dispatch a request message to the appropriate method.
Parameters: msg : Message object
The request message to dispatch.
-
inform_build_state
(msg)¶ Handle katcp v4 and below build-state inform.
-
inform_version
(msg)¶ Handle katcp v4 and below version inform.
-
inform_version_connect
(msg)¶ Process a #version-connect message.
-
is_connected
()¶ Check if the socket is currently connected.
Returns: connected : bool
Whether the client is connected.
-
join
(timeout=None)¶ Rejoin the client thread.
Parameters: timeout : float in seconds
Seconds to wait for thread to finish.
Notes
Does nothing if the ioloop is not managed. Use until_stopped() instead.
-
notify_connected
(connected)¶ Event handler that is called whenever the connection status changes.
Override in derived class for desired behaviour.
Note
This function should never block. Doing so will cause the client to cease processing data from the server until notify_connected completes.
Parameters: connected : bool
Whether the client has just connected (True) or just disconnected (False).
-
preset_protocol_flags
(protocol_flags)¶ Preset server protocol flags.
Sets the assumed server protocol flags and disables automatic server version detection.
Parameters: protocol_flags : katcp.core.ProtocolFlags instance
-
request
(msg, use_mid=None)¶ Send a request message, with automatic message ID assignment.
Parameters: msg : katcp.Message request message
use_mid : bool or None, default=None
Returns: mid : string or None
The message id, or None if no msg id is used
If use_mid is None and the server supports msg ids, or if use_mid is :
True a message ID will automatically be assigned msg.mid is None. :
if msg.mid has a value, and the server supports msg ids, that value :
will be used. If the server does not support msg ids, KatcpVersionError :
will be raised. :
-
running
()¶ Whether the client is running.
Returns: running : bool
Whether the client is running.
-
send_message
(msg)¶ Send any kind of message.
Parameters: msg : Message object
The message to send.
-
send_request
(msg)¶ Send a request message.
Parameters: msg : Message object
The request Message to send.
-
set_ioloop
(ioloop=None)¶ Set the tornado.ioloop.IOLoop instance to use.
This defaults to IOLoop.current(). If set_ioloop() is never called the IOLoop is managed: started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called
-
start
(timeout=None)¶ Start the client in a new thread.
Parameters: timeout : float in seconds
Seconds to wait for client thread to start. Do not specify a timeout if start() is being called from the same ioloop that this client will be installed on, since it will block the ioloop without progressing.
-
stop
(timeout=None)¶ Stop a running client.
If using a managed ioloop, this must be called from a different thread to the ioloop’s. This method only returns once the client’s main coroutine, _install(), has completed.
If using an unmanaged ioloop, this can be called from the same thread as the ioloop. The until_stopped() method can be used to wait on completion of the main coroutine, _install().
Parameters: timeout : float in seconds
Seconds to wait for both client thread to have started, and for stopping.
-
unhandled_inform
(msg)¶ Fallback method for inform messages without a registered handler.
Parameters: msg : Message object
The inform message that wasn’t processed by any handlers.
-
unhandled_reply
(msg)¶ Fallback method for reply messages without a registered handler.
Parameters: msg : Message object
The reply message that wasn’t processed by any handlers.
-
unhandled_request
(msg)¶ Fallback method for requests without a registered handler.
Parameters: msg : Message object
The request message that wasn’t processed by any handlers.
-
until_connected
(**kwargs)¶ Return future that resolves when the client is connected.
-
until_protocol
(**kwargs)¶ Return future that resolves after receipt of katcp protocol info.
If the returned future resolves, the server’s protocol information is available in the ProtocolFlags instance self.protocol_flags.
-
until_running
(timeout=None)¶ Return future that resolves when the client is running.
Notes
Must be called from the same ioloop as the client.
-
until_stopped
(timeout=None)¶ Return future that resolves when the client has stopped.
Parameters: timeout : float in seconds
Seconds to wait for the client to stop.
Notes
If already running, stop() must be called before this.
Must be called from the same ioloop as the client. If using a different thread, or a managed ioloop, this method should not be used. Use join() instead.
Also note that stopped != not running. Stopped means the main coroutine has ended, or was never started. When stopping, the running flag is cleared some time before stopped is set.
-
wait_connected
(timeout=None)¶ Wait until the client is connected.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: connected : bool
Whether the client is connected.
Notes
Do not call this from the ioloop, use until_connected().
-
wait_disconnected
(timeout=None)¶ Wait until the client is disconnected.
Parameters: timeout : float in seconds
Seconds to wait for the client to disconnect.
Returns: disconnected : bool
Whether the client is disconnected.
Notes
Do not call this from the ioloop, use until_disconnected().
-
wait_protocol
(timeout=None)¶ Wait until katcp protocol information has been received from server.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: received : bool
Whether protocol information was received
If this method returns True, the server’s protocol information is :
available in the ProtocolFlags instance self.protocol_flags. :
Notes
Do not call this from the ioloop, use until_protocol().
-
wait_running
(timeout=None)¶ Wait until the client is running.
Parameters: timeout : float in seconds
Seconds to wait for the client to start running.
Returns: running : bool
Whether the client is running
Notes
Do not call this from the ioloop, use until_running().
-
Server¶
AsyncDeviceServer¶
-
class
katcp.
AsyncDeviceServer
(*args, **kwargs)¶ DeviceServer that is automatically configured for async use.
Same as instantiating a
DeviceServer
instance and calling methods set_concurrency_options(thread_safe=False, handler_thread=False) and set_ioloop(tornado.ioloop.IOLoop.current()) before starting.Methods
AsyncDeviceServer.add_sensor
(sensor)Add a sensor to the device. AsyncDeviceServer.build_state
()Return build state string of the form name-major.minor[(a|b|rc)n]. AsyncDeviceServer.clear_strategies
(client_conn)Clear the sensor strategies of a client connection. AsyncDeviceServer.create_exception_reply_and_log
(…)AsyncDeviceServer.create_log_inform
(…[, …])Create a katcp logging inform message. AsyncDeviceServer.get_sensor
(sensor_name)Fetch the sensor with the given name. AsyncDeviceServer.get_sensors
()Fetch a list of all sensors. AsyncDeviceServer.handle_inform
(connection, msg)Dispatch an inform message to the appropriate method. AsyncDeviceServer.handle_message
(…)Handle messages of all types from clients. AsyncDeviceServer.handle_reply
(connection, msg)Dispatch a reply message to the appropriate method. AsyncDeviceServer.handle_request
(connection, msg)Dispatch a request message to the appropriate method. AsyncDeviceServer.has_sensor
(sensor_name)Whether the sensor with specified name is known. AsyncDeviceServer.inform
(connection, msg)Send an inform message to a particular client. AsyncDeviceServer.join
([timeout])Rejoin the server thread. AsyncDeviceServer.mass_inform
(msg)Send an inform message to all clients. AsyncDeviceServer.next
()AsyncDeviceServer.on_client_connect
(**kwargs)Inform client of build state and version on connect. AsyncDeviceServer.on_client_disconnect
(…)Inform client it is about to be disconnected. AsyncDeviceServer.on_message
(client_conn, msg)Dummy implementation of on_message required by KATCPServer. AsyncDeviceServer.remove_sensor
(sensor)Remove a sensor from the device. AsyncDeviceServer.reply
(connection, reply, …)Send an asynchronous reply to an earlier request. AsyncDeviceServer.reply_inform
(connection, …)Send an inform as part of the reply to an earlier request. AsyncDeviceServer.request_client_list
(req, msg)Request the list of connected clients. AsyncDeviceServer.request_halt
(req, msg)Halt the device server. AsyncDeviceServer.request_help
(req, msg)Return help on the available requests. AsyncDeviceServer.request_log_level
(req, msg)Query or set the current logging level. AsyncDeviceServer.request_request_timeout_hint
(…)Return timeout hints for requests AsyncDeviceServer.request_restart
(req, msg)Restart the device server. AsyncDeviceServer.request_sensor_list
(req, msg)Request the list of sensors. AsyncDeviceServer.request_sensor_sampling
(…)Configure or query the way a sensor is sampled. AsyncDeviceServer.request_sensor_sampling_clear
(…)Set all sampling strategies for this client to none. AsyncDeviceServer.request_sensor_value
(req, msg)Request the value of a sensor or sensors. AsyncDeviceServer.request_version_list
(req, msg)Request the list of versions of roles and subcomponents. AsyncDeviceServer.request_watchdog
(req, msg)Check that the server is still alive. AsyncDeviceServer.running
()Whether the server is running. AsyncDeviceServer.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False AsyncDeviceServer.set_concurrency_options
([…])Set concurrency options for this device server. AsyncDeviceServer.set_ioloop
([ioloop])Set the tornado IOLoop to use. AsyncDeviceServer.set_restart_queue
(…)Set the restart queue. AsyncDeviceServer.setup_sensors
()Populate the dictionary of sensors. AsyncDeviceServer.start
([timeout])Start the server in a new thread. AsyncDeviceServer.stop
([timeout])Stop a running server (from another thread). AsyncDeviceServer.sync_with_ioloop
([timeout])Block for ioloop to complete a loop if called from another thread. AsyncDeviceServer.version
()Return a version string of the form type-major.minor. AsyncDeviceServer.wait_running
([timeout])Wait until the server is running -
add_sensor
(sensor)¶ Add a sensor to the device.
Usually called inside .setup_sensors() but may be called from elsewhere.
Parameters: sensor : Sensor object
The sensor object to register with the device server.
-
build_state
()¶ Return build state string of the form name-major.minor[(a|b|rc)n].
-
clear_strategies
(client_conn, remove_client=False)¶ Clear the sensor strategies of a client connection.
Parameters: client_connection : ClientConnection instance
The connection that should have its sampling strategies cleared
remove_client : bool, optional
Remove the client connection from the strategies data-structure. Useful for clients that disconnect.
-
create_log_inform
(level_name, msg, name, timestamp=None)¶ Create a katcp logging inform message.
Usually this will be called from inside a DeviceLogger object, but it is also used by the methods in this class when errors need to be reported to the client.
-
get_sensor
(sensor_name)¶ Fetch the sensor with the given name.
Parameters: sensor_name : str
Name of the sensor to retrieve.
Returns: sensor : Sensor object
The sensor with the given name.
-
get_sensors
()¶ Fetch a list of all sensors.
Returns: sensors : list of Sensor objects
The list of sensors registered with the device server.
-
handle_inform
(connection, msg)¶ Dispatch an inform message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The inform message to process.
-
handle_message
(client_conn, msg)¶ Handle messages of all types from clients.
Parameters: client_conn : ClientConnection object
The client connection the message was from.
msg : Message object
The message to process.
-
handle_reply
(connection, msg)¶ Dispatch a reply message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The reply message to process.
-
handle_request
(connection, msg)¶ Dispatch a request message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The request message to process.
Returns: done_future : Future or None
Returns Future for async request handlers that will resolve when done, or None for sync request handlers once they have completed.
-
has_sensor
(sensor_name)¶ Whether the sensor with specified name is known.
-
inform
(connection, msg)¶ Send an inform message to a particular client.
Should only be used for asynchronous informs. Informs that are part of the response to a request should use
reply_inform()
so that the message identifier from the original request can be attached to the inform.Parameters: connection : ClientConnection object
The client to send the message to.
msg : Message object
The inform message to send.
-
join
(timeout=None)¶ Rejoin the server thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for the thread to finish.
-
mass_inform
(msg)¶ Send an inform message to all clients.
Parameters: msg : Message object
The inform message to send.
-
on_client_connect
(**kwargs)¶ Inform client of build state and version on connect.
Parameters: client_conn : ClientConnection object
The client connection that has been successfully established.
Returns: Future that resolves when the device is ready to accept messages. :
-
on_client_disconnect
(client_conn, msg, connection_valid)¶ Inform client it is about to be disconnected.
Parameters: client_conn : ClientConnection object
The client connection being disconnected.
msg : str
Reason client is being disconnected.
connection_valid : bool
True if connection is still open for sending, False otherwise.
Returns: Future that resolves when the client connection can be closed. :
-
on_message
(client_conn, msg)¶ Dummy implementation of on_message required by KATCPServer.
Will be replaced by a handler with the appropriate concurrency semantics when set_concurrency_options is called (defaults are set in __init__()).
-
remove_sensor
(sensor)¶ Remove a sensor from the device.
Also deregisters all clients observing the sensor.
Parameters: sensor : Sensor object or name string
The sensor to remove from the device server.
-
reply
(connection, reply, orig_req)¶ Send an asynchronous reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the reply to.
reply : Message object
The reply message to send.
orig_req : Message object
The request message being replied to. The reply message’s id is overridden with the id from orig_req before the reply is sent.
-
reply_inform
(connection, inform, orig_req)¶ Send an inform as part of the reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the inform to.
inform : Message object
The inform message to send.
orig_req : Message object
The request message being replied to. The inform message’s id is overridden with the id from orig_req before the inform is sent.
-
request_client_list
(req, msg)¶ Request the list of connected clients.
The list of clients is sent as a sequence of #client-list informs.
Informs: addr : str
The address of the client as host:port with host in dotted quad notation. If the address of the client could not be determined (because, for example, the client disconnected suddenly) then a unique string representing the client is sent instead.
Returns: success : {‘ok’, ‘fail’}
Whether sending the client list succeeded.
informs : int
Number of #client-list inform messages sent.
Examples
?client-list #client-list 127.0.0.1:53600 !client-list ok 1
-
request_halt
(req, msg)¶ Halt the device server.
Returns: success : {‘ok’, ‘fail’}
Whether scheduling the halt succeeded.
Examples
?halt !halt ok
-
request_help
(req, msg)¶ Return help on the available requests.
Return a description of the available requests using a sequence of #help informs.
Parameters: request : str, optional
The name of the request to return help for (the default is to return help for all requests).
Informs: request : str
The name of a request.
description : str
Documentation for the named request.
Returns: success : {‘ok’, ‘fail’}
Whether sending the help succeeded.
informs : int
Number of #help inform messages sent.
Examples
?help #help halt ...description... #help help ...description... ... !help ok 5 ?help halt #help halt ...description... !help ok 1
-
request_log_level
(req, msg)¶ Query or set the current logging level.
Parameters: level : {‘all’, ‘trace’, ‘debug’, ‘info’, ‘warn’, ‘error’, ‘fatal’, ‘off’}, optional
Name of the logging level to set the device server to (the default is to leave the log level unchanged).
Returns: success : {‘ok’, ‘fail’}
Whether the request succeeded.
level : {‘all’, ‘trace’, ‘debug’, ‘info’, ‘warn’, ‘error’, ‘fatal’, ‘off’}
The log level after processing the request.
Examples
?log-level !log-level ok warn ?log-level info !log-level ok info
-
request_request_timeout_hint
(req, msg)¶ Return timeout hints for requests
KATCP requests should generally take less than 5s to complete, but some requests are unavoidably slow. This results in spurious client timeout errors. This request provides timeout hints that clients can use to select suitable request timeouts.
Parameters: request : str, optional
The name of the request to return a timeout hint for (the default is to return hints for all requests that have timeout hints). Returns one inform per request. Must be an existing request if specified.
Informs: request : str
The name of the request.
suggested_timeout : float
Suggested request timeout in seconds for the request. If suggested_timeout is zero (0), no timeout hint is available.
Returns: success : {‘ok’, ‘fail’}
Whether sending the help succeeded.
informs : int
Number of #request-timeout-hint inform messages sent.
Notes
?request-timeout-hint without a parameter will only return informs for requests that have specific timeout hints, so it will most probably be a subset of all the requests, or even no informs at all.
Examples
?request-timeout-hint #request-timeout-hint halt 5 #request-timeout-hint very-slow-request 500 ... !request-timeout-hint ok 5 ?request-timeout-hint moderately-slow-request #request-timeout-hint moderately-slow-request 20 !request-timeout-hint ok 1
-
request_restart
(req, msg)¶ Restart the device server.
Returns: success : {‘ok’, ‘fail’}
Whether scheduling the restart succeeded.
Examples
?restart !restart ok
-
request_sensor_list
(req, msg)¶ Request the list of sensors.
The list of sensors is sent as a sequence of #sensor-list informs.
Parameters: name : str, optional
Name of the sensor to list (the default is to list all sensors). If name starts and ends with ‘/’ it is treated as a regular expression and all sensors whose names contain the regular expression are returned.
Informs: name : str
The name of the sensor being described.
description : str
Description of the named sensor.
units : str
Units for the value of the named sensor.
type : str
Type of the named sensor.
params : list of str, optional
Additional sensor parameters (type dependent). For integer and float sensors the additional parameters are the minimum and maximum sensor value. For discrete sensors the additional parameters are the allowed values. For all other types no additional parameters are sent.
Returns: success : {‘ok’, ‘fail’}
Whether sending the sensor list succeeded.
informs : int
Number of #sensor-list inform messages sent.
Examples
?sensor-list #sensor-list psu.voltage PSU\_voltage. V float 0.0 5.0 #sensor-list cpu.status CPU\_status. \@ discrete on off error ... !sensor-list ok 5 ?sensor-list cpu.power.on #sensor-list cpu.power.on Whether\_CPU\_hase\_power. \@ boolean !sensor-list ok 1 ?sensor-list /voltage/ #sensor-list psu.voltage PSU\_voltage. V float 0.0 5.0 #sensor-list cpu.voltage CPU\_voltage. V float 0.0 3.0 !sensor-list ok 2
-
request_sensor_sampling
(req, msg)¶ Configure or query the way a sensor is sampled.
Sampled values are reported asynchronously using the #sensor-status message.
Parameters: names : str
One or more names of sensors whose sampling strategy will be queried or configured. If specifying multiple sensors, these must be provided as a comma-separated list. A query can only be done on a single sensor. However, configuration can be done on many sensors with a single request, as long as they all use the same strategy. Note: prior to KATCP v5.1 only a single sensor could be configured. Multiple sensors are only allowed if the device server sets the protocol version to KATCP v5.1 or higher and enables the BULK_SET_SENSOR_SAMPLING flag in its PROTOCOL_INFO class attribute.
strategy : {‘none’, ‘auto’, ‘event’, ‘differential’, ‘differential-rate’,
‘period’, ‘event-rate’}, optional
Type of strategy to use to report the sensor value. The differential strategy types may only be used with integer or float sensors. If this parameter is supplied, it sets the new strategy.
params : list of str, optional
Additional strategy parameters (dependent on the strategy type). For the differential strategy, the parameter is an integer or float giving the amount by which the sensor value may change before an updated value is sent. For the period strategy, the parameter is the sampling period in float seconds. The event strategy has no parameters. Note that this has changed from KATCPv4. For the event-rate strategy, a minimum period between updates and a maximum period between updates (both in float seconds) must be given. If the event occurs more than once within the minimum period, only one update will occur. Whether or not the event occurs, the sensor value will be updated at least once per maximum period. For the differential-rate strategy there are 3 parameters. The first is the same as the differential strategy parameter. The second and third are the minimum and maximum periods, respectively, as with the event-rate strategy.
Informs: timestamp : float
Timestamp of the sensor reading in seconds since the Unix epoch, or milliseconds for katcp versions <= 4.
count : {1}
Number of sensors described in this #sensor-status inform. Will always be one. It exists to keep this inform compatible with #sensor-value.
name : str
Name of the sensor whose value is being reported.
value : object
Value of the named sensor. Type depends on the type of the sensor.
Returns: success : {‘ok’, ‘fail’}
Whether the sensor-sampling request succeeded.
names : str
Name(s) of the sensor queried or configured. If multiple sensors, this will be a comma-separated list.
strategy : {‘none’, ‘auto’, ‘event’, ‘differential’, ‘differential-rate’,
‘period’, ‘event-rate’}.
Name of the new or current sampling strategy for the sensor(s).
params : list of str
Additional strategy parameters (see description under Parameters).
Examples :
——– :
:: :
?sensor-sampling cpu.power.on !sensor-sampling ok cpu.power.on none
?sensor-sampling cpu.power.on period 0.5 #sensor-status 1244631611.415231 1 cpu.power.on nominal 1 !sensor-sampling ok cpu.power.on period 0.5
if BULK_SET_SENSOR_SAMPLING is enabled then:
?sensor-sampling cpu.power.on,fan.speed !sensor-sampling fail Cannot_query_multiple_sensors
?sensor-sampling cpu.power.on,fan.speed period 0.5 #sensor-status 1244631611.415231 1 cpu.power.on nominal 1 #sensor-status 1244631611.415200 1 fan.speed nominal 10.0 !sensor-sampling ok cpu.power.on,fan.speed period 0.5
-
request_sensor_sampling_clear
(req, msg)¶ Set all sampling strategies for this client to none.
Returns: success : {‘ok’, ‘fail’}
Whether sending the list of devices succeeded.
Examples
?sensor-sampling-clear !sensor-sampling-clear ok
-
request_sensor_value
(req, msg)¶ Request the value of a sensor or sensors.
A list of sensor values as a sequence of #sensor-value informs.
Parameters: name : str, optional
Name of the sensor to poll (the default is to send values for all sensors). If name starts and ends with ‘/’ it is treated as a regular expression and all sensors whose names contain the regular expression are returned.
Informs: timestamp : float
Timestamp of the sensor reading in seconds since the Unix epoch, or milliseconds for katcp versions <= 4.
count : {1}
Number of sensors described in this #sensor-value inform. Will always be one. It exists to keep this inform compatible with #sensor-status.
name : str
Name of the sensor whose value is being reported.
value : object
Value of the named sensor. Type depends on the type of the sensor.
Returns: success : {‘ok’, ‘fail’}
Whether sending the list of values succeeded.
informs : int
Number of #sensor-value inform messages sent.
Examples
?sensor-value #sensor-value 1244631611.415231 1 psu.voltage nominal 4.5 #sensor-value 1244631611.415200 1 cpu.status nominal off ... !sensor-value ok 5 ?sensor-value cpu.power.on #sensor-value 1244631611.415231 1 cpu.power.on nominal 0 !sensor-value ok 1
-
request_version_list
(req, msg)¶ Request the list of versions of roles and subcomponents.
Informs: name : str
Name of the role or component.
version : str
A string identifying the version of the component. Individual components may define the structure of this argument as they choose. In the absence of other information clients should treat it as an opaque string.
build_state_or_serial_number : str
A unique identifier for a particular instance of a component. This should change whenever the component is replaced or updated.
Returns: success : {‘ok’, ‘fail’}
Whether sending the version list succeeded.
informs : int
Number of #version-list inform messages sent.
Examples
?version-list #version-list katcp-protocol 5.0-MI #version-list katcp-library katcp-python-0.4 katcp-python-0.4.1-py2 #version-list katcp-device foodevice-1.0 foodevice-1.0.0rc1 !version-list ok 3
-
request_watchdog
(req, msg)¶ Check that the server is still alive.
Returns: success : {‘ok’} Examples
?watchdog !watchdog ok
-
running
()¶ Whether the server is running.
-
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
set_concurrency_options
(thread_safe=True, handler_thread=True)¶ Set concurrency options for this device server. Must be called before
start()
.Parameters: thread_safe : bool
If True, make the server public methods thread safe. Incurs performance overhead.
handler_thread : bool
Can only be set if thread_safe is True. Handle all requests (even from different clients) in a separate, single, request-handling thread. Blocking request handlers will prevent the server from handling new requests from any client, but sensor strategies should still function. This more or less mimics the behaviour of a server in library versions before 0.6.0.
-
set_ioloop
(ioloop=None)¶ Set the tornado IOLoop to use.
Sets the tornado.ioloop.IOLoop instance to use, defaulting to IOLoop.current(). If set_ioloop() is never called the IOLoop is started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called.
-
set_restart_queue
(restart_queue)¶ Set the restart queue.
When the device server should be restarted, it will be added to the queue.
Parameters: restart_queue : Queue.Queue object
The queue to add the device server to when it should be restarted.
-
setup_sensors
()¶ Populate the dictionary of sensors.
Unimplemented by default – subclasses should add their sensors here or pass if there are no sensors.
Examples
>>> class MyDevice(DeviceServer): ... def setup_sensors(self): ... self.add_sensor(Sensor(...)) ... self.add_sensor(Sensor(...)) ...
-
start
(timeout=None)¶ Start the server in a new thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for server thread to start.
-
stop
(timeout=1.0)¶ Stop a running server (from another thread).
Parameters: timeout : float, optional
Seconds to wait for server to have started.
Returns: stopped : thread-safe Future
Resolves when the server is stopped
-
sync_with_ioloop
(timeout=None)¶ Block for ioloop to complete a loop if called from another thread.
Returns a future if called from inside the ioloop.
Raises concurrent.futures.TimeoutError if timed out while blocking.
-
version
()¶ Return a version string of the form type-major.minor.
-
wait_running
(timeout=None)¶ Wait until the server is running
-
DeviceServer¶
-
class
katcp.
DeviceServer
(*args, **kwargs)¶ Implements some standard messages on top of DeviceServerBase.
Inform messages handled are:
- version (sent on connect)
- build-state (sent on connect)
- log (via self.log.warn(…), etc)
- disconnect
- client-connected
Requests handled are:
- halt
- help
- log-level
- restart [1]
- client-list
- sensor-list
- sensor-sampling
- sensor-value
- watchdog
- version-list (only standard in KATCP v5 or later)
- request-timeout-hint (pre-standard only if protocol flags indicates
- timeout hints, supported for KATCP v5.1 or later)
- sensor-sampling-clear (non-standard)
[1] Restart relies on .set_restart_queue() being used to register a restart queue with the device. When the device needs to be restarted, it will be added to the restart queue. The queue should be a Python Queue.Queue object without a maximum size. Unhandled standard requests are:
- configure
- mode
Subclasses can define the tuple VERSION_INFO to set the interface name, major and minor version numbers. The BUILD_INFO tuple can be defined to give a string describing a particular interface instance and may have a fourth element containing additional version information (e.g. rc1).
Subclasses may manipulate the versions returned by the ?version-list command by editing .extra_versions which is a dictionary mapping role or component names to (version, build_state_or_serial_no) tuples. The build_state_or_serial_no may be None.
Subclasses must override the .setup_sensors() method. If they have no sensors to register, the method should just be a pass.
Methods
DeviceServer.add_sensor
(sensor)Add a sensor to the device. DeviceServer.build_state
()Return build state string of the form name-major.minor[(a|b|rc)n]. DeviceServer.clear_strategies
(client_conn[, …])Clear the sensor strategies of a client connection. DeviceServer.create_exception_reply_and_log
(…)DeviceServer.create_log_inform
(level_name, …)Create a katcp logging inform message. DeviceServer.get_sensor
(sensor_name)Fetch the sensor with the given name. DeviceServer.get_sensors
()Fetch a list of all sensors. DeviceServer.handle_inform
(connection, msg)Dispatch an inform message to the appropriate method. DeviceServer.handle_message
(client_conn, msg)Handle messages of all types from clients. DeviceServer.handle_reply
(connection, msg)Dispatch a reply message to the appropriate method. DeviceServer.handle_request
(connection, msg)Dispatch a request message to the appropriate method. DeviceServer.has_sensor
(sensor_name)Whether the sensor with specified name is known. DeviceServer.inform
(connection, msg)Send an inform message to a particular client. DeviceServer.join
([timeout])Rejoin the server thread. DeviceServer.mass_inform
(msg)Send an inform message to all clients. DeviceServer.next
()DeviceServer.on_client_connect
(**kwargs)Inform client of build state and version on connect. DeviceServer.on_client_disconnect
(…)Inform client it is about to be disconnected. DeviceServer.on_message
(client_conn, msg)Dummy implementation of on_message required by KATCPServer. DeviceServer.remove_sensor
(sensor)Remove a sensor from the device. DeviceServer.reply
(connection, reply, orig_req)Send an asynchronous reply to an earlier request. DeviceServer.reply_inform
(connection, …)Send an inform as part of the reply to an earlier request. DeviceServer.request_client_list
(req, msg)Request the list of connected clients. DeviceServer.request_halt
(req, msg)Halt the device server. DeviceServer.request_help
(req, msg)Return help on the available requests. DeviceServer.request_log_level
(req, msg)Query or set the current logging level. DeviceServer.request_request_timeout_hint
(…)Return timeout hints for requests DeviceServer.request_restart
(req, msg)Restart the device server. DeviceServer.request_sensor_list
(req, msg)Request the list of sensors. DeviceServer.request_sensor_sampling
(req, msg)Configure or query the way a sensor is sampled. DeviceServer.request_sensor_sampling_clear
(…)Set all sampling strategies for this client to none. DeviceServer.request_sensor_value
(req, msg)Request the value of a sensor or sensors. DeviceServer.request_version_list
(req, msg)Request the list of versions of roles and subcomponents. DeviceServer.request_watchdog
(req, msg)Check that the server is still alive. DeviceServer.running
()Whether the server is running. DeviceServer.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False DeviceServer.set_concurrency_options
([…])Set concurrency options for this device server. DeviceServer.set_ioloop
([ioloop])Set the tornado IOLoop to use. DeviceServer.set_restart_queue
(restart_queue)Set the restart queue. DeviceServer.setup_sensors
()Populate the dictionary of sensors. DeviceServer.start
([timeout])Start the server in a new thread. DeviceServer.stop
([timeout])Stop a running server (from another thread). DeviceServer.sync_with_ioloop
([timeout])Block for ioloop to complete a loop if called from another thread. DeviceServer.version
()Return a version string of the form type-major.minor. DeviceServer.wait_running
([timeout])Wait until the server is running -
add_sensor
(sensor)¶ Add a sensor to the device.
Usually called inside .setup_sensors() but may be called from elsewhere.
Parameters: sensor : Sensor object
The sensor object to register with the device server.
-
build_state
()¶ Return build state string of the form name-major.minor[(a|b|rc)n].
-
clear_strategies
(client_conn, remove_client=False)¶ Clear the sensor strategies of a client connection.
Parameters: client_connection : ClientConnection instance
The connection that should have its sampling strategies cleared
remove_client : bool, optional
Remove the client connection from the strategies data-structure. Useful for clients that disconnect.
-
create_log_inform
(level_name, msg, name, timestamp=None)¶ Create a katcp logging inform message.
Usually this will be called from inside a DeviceLogger object, but it is also used by the methods in this class when errors need to be reported to the client.
-
get_sensor
(sensor_name)¶ Fetch the sensor with the given name.
Parameters: sensor_name : str
Name of the sensor to retrieve.
Returns: sensor : Sensor object
The sensor with the given name.
-
get_sensors
()¶ Fetch a list of all sensors.
Returns: sensors : list of Sensor objects
The list of sensors registered with the device server.
-
handle_inform
(connection, msg)¶ Dispatch an inform message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The inform message to process.
-
handle_message
(client_conn, msg)¶ Handle messages of all types from clients.
Parameters: client_conn : ClientConnection object
The client connection the message was from.
msg : Message object
The message to process.
-
handle_reply
(connection, msg)¶ Dispatch a reply message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The reply message to process.
-
handle_request
(connection, msg)¶ Dispatch a request message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The request message to process.
Returns: done_future : Future or None
Returns Future for async request handlers that will resolve when done, or None for sync request handlers once they have completed.
-
has_sensor
(sensor_name)¶ Whether the sensor with specified name is known.
-
inform
(connection, msg)¶ Send an inform message to a particular client.
Should only be used for asynchronous informs. Informs that are part of the response to a request should use
reply_inform()
so that the message identifier from the original request can be attached to the inform.Parameters: connection : ClientConnection object
The client to send the message to.
msg : Message object
The inform message to send.
-
join
(timeout=None)¶ Rejoin the server thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for the thread to finish.
-
mass_inform
(msg)¶ Send an inform message to all clients.
Parameters: msg : Message object
The inform message to send.
-
on_client_connect
(**kwargs)¶ Inform client of build state and version on connect.
Parameters: client_conn : ClientConnection object
The client connection that has been successfully established.
Returns: Future that resolves when the device is ready to accept messages. :
-
on_client_disconnect
(client_conn, msg, connection_valid)¶ Inform client it is about to be disconnected.
Parameters: client_conn : ClientConnection object
The client connection being disconnected.
msg : str
Reason client is being disconnected.
connection_valid : bool
True if connection is still open for sending, False otherwise.
Returns: Future that resolves when the client connection can be closed. :
-
on_message
(client_conn, msg)¶ Dummy implementation of on_message required by KATCPServer.
Will be replaced by a handler with the appropriate concurrency semantics when set_concurrency_options is called (defaults are set in __init__()).
-
remove_sensor
(sensor)¶ Remove a sensor from the device.
Also deregisters all clients observing the sensor.
Parameters: sensor : Sensor object or name string
The sensor to remove from the device server.
-
reply
(connection, reply, orig_req)¶ Send an asynchronous reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the reply to.
reply : Message object
The reply message to send.
orig_req : Message object
The request message being replied to. The reply message’s id is overridden with the id from orig_req before the reply is sent.
-
reply_inform
(connection, inform, orig_req)¶ Send an inform as part of the reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the inform to.
inform : Message object
The inform message to send.
orig_req : Message object
The request message being replied to. The inform message’s id is overridden with the id from orig_req before the inform is sent.
-
request_client_list
(req, msg)¶ Request the list of connected clients.
The list of clients is sent as a sequence of #client-list informs.
Informs: addr : str
The address of the client as host:port with host in dotted quad notation. If the address of the client could not be determined (because, for example, the client disconnected suddenly) then a unique string representing the client is sent instead.
Returns: success : {‘ok’, ‘fail’}
Whether sending the client list succeeded.
informs : int
Number of #client-list inform messages sent.
Examples
?client-list #client-list 127.0.0.1:53600 !client-list ok 1
-
request_halt
(req, msg)¶ Halt the device server.
Returns: success : {‘ok’, ‘fail’}
Whether scheduling the halt succeeded.
Examples
?halt !halt ok
-
request_help
(req, msg)¶ Return help on the available requests.
Return a description of the available requests using a sequence of #help informs.
Parameters: request : str, optional
The name of the request to return help for (the default is to return help for all requests).
Informs: request : str
The name of a request.
description : str
Documentation for the named request.
Returns: success : {‘ok’, ‘fail’}
Whether sending the help succeeded.
informs : int
Number of #help inform messages sent.
Examples
?help #help halt ...description... #help help ...description... ... !help ok 5 ?help halt #help halt ...description... !help ok 1
-
request_log_level
(req, msg)¶ Query or set the current logging level.
Parameters: level : {‘all’, ‘trace’, ‘debug’, ‘info’, ‘warn’, ‘error’, ‘fatal’, ‘off’}, optional
Name of the logging level to set the device server to (the default is to leave the log level unchanged).
Returns: success : {‘ok’, ‘fail’}
Whether the request succeeded.
level : {‘all’, ‘trace’, ‘debug’, ‘info’, ‘warn’, ‘error’, ‘fatal’, ‘off’}
The log level after processing the request.
Examples
?log-level !log-level ok warn ?log-level info !log-level ok info
-
request_request_timeout_hint
(req, msg)¶ Return timeout hints for requests
KATCP requests should generally take less than 5s to complete, but some requests are unavoidably slow. This results in spurious client timeout errors. This request provides timeout hints that clients can use to select suitable request timeouts.
Parameters: request : str, optional
The name of the request to return a timeout hint for (the default is to return hints for all requests that have timeout hints). Returns one inform per request. Must be an existing request if specified.
Informs: request : str
The name of the request.
suggested_timeout : float
Suggested request timeout in seconds for the request. If suggested_timeout is zero (0), no timeout hint is available.
Returns: success : {‘ok’, ‘fail’}
Whether sending the help succeeded.
informs : int
Number of #request-timeout-hint inform messages sent.
Notes
?request-timeout-hint without a parameter will only return informs for requests that have specific timeout hints, so it will most probably be a subset of all the requests, or even no informs at all.
Examples
?request-timeout-hint #request-timeout-hint halt 5 #request-timeout-hint very-slow-request 500 ... !request-timeout-hint ok 5 ?request-timeout-hint moderately-slow-request #request-timeout-hint moderately-slow-request 20 !request-timeout-hint ok 1
-
request_restart
(req, msg)¶ Restart the device server.
Returns: success : {‘ok’, ‘fail’}
Whether scheduling the restart succeeded.
Examples
?restart !restart ok
-
request_sensor_list
(req, msg)¶ Request the list of sensors.
The list of sensors is sent as a sequence of #sensor-list informs.
Parameters: name : str, optional
Name of the sensor to list (the default is to list all sensors). If name starts and ends with ‘/’ it is treated as a regular expression and all sensors whose names contain the regular expression are returned.
Informs: name : str
The name of the sensor being described.
description : str
Description of the named sensor.
units : str
Units for the value of the named sensor.
type : str
Type of the named sensor.
params : list of str, optional
Additional sensor parameters (type dependent). For integer and float sensors the additional parameters are the minimum and maximum sensor value. For discrete sensors the additional parameters are the allowed values. For all other types no additional parameters are sent.
Returns: success : {‘ok’, ‘fail’}
Whether sending the sensor list succeeded.
informs : int
Number of #sensor-list inform messages sent.
Examples
?sensor-list #sensor-list psu.voltage PSU\_voltage. V float 0.0 5.0 #sensor-list cpu.status CPU\_status. \@ discrete on off error ... !sensor-list ok 5 ?sensor-list cpu.power.on #sensor-list cpu.power.on Whether\_CPU\_hase\_power. \@ boolean !sensor-list ok 1 ?sensor-list /voltage/ #sensor-list psu.voltage PSU\_voltage. V float 0.0 5.0 #sensor-list cpu.voltage CPU\_voltage. V float 0.0 3.0 !sensor-list ok 2
-
request_sensor_sampling
(req, msg)¶ Configure or query the way a sensor is sampled.
Sampled values are reported asynchronously using the #sensor-status message.
Parameters: names : str
One or more names of sensors whose sampling strategy will be queried or configured. If specifying multiple sensors, these must be provided as a comma-separated list. A query can only be done on a single sensor. However, configuration can be done on many sensors with a single request, as long as they all use the same strategy. Note: prior to KATCP v5.1 only a single sensor could be configured. Multiple sensors are only allowed if the device server sets the protocol version to KATCP v5.1 or higher and enables the BULK_SET_SENSOR_SAMPLING flag in its PROTOCOL_INFO class attribute.
strategy : {‘none’, ‘auto’, ‘event’, ‘differential’, ‘differential-rate’,
‘period’, ‘event-rate’}, optional
Type of strategy to use to report the sensor value. The differential strategy types may only be used with integer or float sensors. If this parameter is supplied, it sets the new strategy.
params : list of str, optional
Additional strategy parameters (dependent on the strategy type). For the differential strategy, the parameter is an integer or float giving the amount by which the sensor value may change before an updated value is sent. For the period strategy, the parameter is the sampling period in float seconds. The event strategy has no parameters. Note that this has changed from KATCPv4. For the event-rate strategy, a minimum period between updates and a maximum period between updates (both in float seconds) must be given. If the event occurs more than once within the minimum period, only one update will occur. Whether or not the event occurs, the sensor value will be updated at least once per maximum period. For the differential-rate strategy there are 3 parameters. The first is the same as the differential strategy parameter. The second and third are the minimum and maximum periods, respectively, as with the event-rate strategy.
Informs: timestamp : float
Timestamp of the sensor reading in seconds since the Unix epoch, or milliseconds for katcp versions <= 4.
count : {1}
Number of sensors described in this #sensor-status inform. Will always be one. It exists to keep this inform compatible with #sensor-value.
name : str
Name of the sensor whose value is being reported.
value : object
Value of the named sensor. Type depends on the type of the sensor.
Returns: success : {‘ok’, ‘fail’}
Whether the sensor-sampling request succeeded.
names : str
Name(s) of the sensor queried or configured. If multiple sensors, this will be a comma-separated list.
strategy : {‘none’, ‘auto’, ‘event’, ‘differential’, ‘differential-rate’,
‘period’, ‘event-rate’}.
Name of the new or current sampling strategy for the sensor(s).
params : list of str
Additional strategy parameters (see description under Parameters).
Examples :
——– :
:: :
?sensor-sampling cpu.power.on !sensor-sampling ok cpu.power.on none
?sensor-sampling cpu.power.on period 0.5 #sensor-status 1244631611.415231 1 cpu.power.on nominal 1 !sensor-sampling ok cpu.power.on period 0.5
if BULK_SET_SENSOR_SAMPLING is enabled then:
?sensor-sampling cpu.power.on,fan.speed !sensor-sampling fail Cannot_query_multiple_sensors
?sensor-sampling cpu.power.on,fan.speed period 0.5 #sensor-status 1244631611.415231 1 cpu.power.on nominal 1 #sensor-status 1244631611.415200 1 fan.speed nominal 10.0 !sensor-sampling ok cpu.power.on,fan.speed period 0.5
-
request_sensor_sampling_clear
(req, msg)¶ Set all sampling strategies for this client to none.
Returns: success : {‘ok’, ‘fail’}
Whether sending the list of devices succeeded.
Examples
?sensor-sampling-clear !sensor-sampling-clear ok
-
request_sensor_value
(req, msg)¶ Request the value of a sensor or sensors.
A list of sensor values as a sequence of #sensor-value informs.
Parameters: name : str, optional
Name of the sensor to poll (the default is to send values for all sensors). If name starts and ends with ‘/’ it is treated as a regular expression and all sensors whose names contain the regular expression are returned.
Informs: timestamp : float
Timestamp of the sensor reading in seconds since the Unix epoch, or milliseconds for katcp versions <= 4.
count : {1}
Number of sensors described in this #sensor-value inform. Will always be one. It exists to keep this inform compatible with #sensor-status.
name : str
Name of the sensor whose value is being reported.
value : object
Value of the named sensor. Type depends on the type of the sensor.
Returns: success : {‘ok’, ‘fail’}
Whether sending the list of values succeeded.
informs : int
Number of #sensor-value inform messages sent.
Examples
?sensor-value #sensor-value 1244631611.415231 1 psu.voltage nominal 4.5 #sensor-value 1244631611.415200 1 cpu.status nominal off ... !sensor-value ok 5 ?sensor-value cpu.power.on #sensor-value 1244631611.415231 1 cpu.power.on nominal 0 !sensor-value ok 1
-
request_version_list
(req, msg)¶ Request the list of versions of roles and subcomponents.
Informs: name : str
Name of the role or component.
version : str
A string identifying the version of the component. Individual components may define the structure of this argument as they choose. In the absence of other information clients should treat it as an opaque string.
build_state_or_serial_number : str
A unique identifier for a particular instance of a component. This should change whenever the component is replaced or updated.
Returns: success : {‘ok’, ‘fail’}
Whether sending the version list succeeded.
informs : int
Number of #version-list inform messages sent.
Examples
?version-list #version-list katcp-protocol 5.0-MI #version-list katcp-library katcp-python-0.4 katcp-python-0.4.1-py2 #version-list katcp-device foodevice-1.0 foodevice-1.0.0rc1 !version-list ok 3
-
request_watchdog
(req, msg)¶ Check that the server is still alive.
Returns: success : {‘ok’} Examples
?watchdog !watchdog ok
-
running
()¶ Whether the server is running.
-
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
set_concurrency_options
(thread_safe=True, handler_thread=True)¶ Set concurrency options for this device server. Must be called before
start()
.Parameters: thread_safe : bool
If True, make the server public methods thread safe. Incurs performance overhead.
handler_thread : bool
Can only be set if thread_safe is True. Handle all requests (even from different clients) in a separate, single, request-handling thread. Blocking request handlers will prevent the server from handling new requests from any client, but sensor strategies should still function. This more or less mimics the behaviour of a server in library versions before 0.6.0.
-
set_ioloop
(ioloop=None)¶ Set the tornado IOLoop to use.
Sets the tornado.ioloop.IOLoop instance to use, defaulting to IOLoop.current(). If set_ioloop() is never called the IOLoop is started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called.
-
set_restart_queue
(restart_queue)¶ Set the restart queue.
When the device server should be restarted, it will be added to the queue.
Parameters: restart_queue : Queue.Queue object
The queue to add the device server to when it should be restarted.
-
setup_sensors
()¶ Populate the dictionary of sensors.
Unimplemented by default – subclasses should add their sensors here or pass if there are no sensors.
Examples
>>> class MyDevice(DeviceServer): ... def setup_sensors(self): ... self.add_sensor(Sensor(...)) ... self.add_sensor(Sensor(...)) ...
-
start
(timeout=None)¶ Start the server in a new thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for server thread to start.
-
stop
(timeout=1.0)¶ Stop a running server (from another thread).
Parameters: timeout : float, optional
Seconds to wait for server to have started.
Returns: stopped : thread-safe Future
Resolves when the server is stopped
-
sync_with_ioloop
(timeout=None)¶ Block for ioloop to complete a loop if called from another thread.
Returns a future if called from inside the ioloop.
Raises concurrent.futures.TimeoutError if timed out while blocking.
-
version
()¶ Return a version string of the form type-major.minor.
-
wait_running
(timeout=None)¶ Wait until the server is running
DeviceServerBase¶
-
class
katcp.
DeviceServerBase
(host, port, tb_limit=20, logger=<logging.Logger object>)¶ Base class for device servers.
Subclasses should add .request_* methods for dealing with request messages. These methods each take the client request connection and msg objects as arguments and should return the reply message or raise an exception as a result.
Subclasses can also add .inform_* and reply_* methods to handle those types of messages.
Should a subclass need to generate inform messages it should do so using either the .inform() or .mass_inform() methods.
Finally, this class should probably not be subclassed directly but rather via subclassing DeviceServer itself which implements common .request_* methods.
Parameters: host : str
Host to listen on.
port : int
Port to listen on.
tb_limit : int, optional
Maximum number of stack frames to send in error tracebacks.
logger : logging.Logger object, optional
Logger to log messages to.
Methods
DeviceServerBase.create_exception_reply_and_log
(…)DeviceServerBase.create_log_inform
(…[, …])Create a katcp logging inform message. DeviceServerBase.handle_inform
(connection, msg)Dispatch an inform message to the appropriate method. DeviceServerBase.handle_message
(client_conn, msg)Handle messages of all types from clients. DeviceServerBase.handle_reply
(connection, msg)Dispatch a reply message to the appropriate method. DeviceServerBase.handle_request
(connection, msg)Dispatch a request message to the appropriate method. DeviceServerBase.inform
(connection, msg)Send an inform message to a particular client. DeviceServerBase.join
([timeout])Rejoin the server thread. DeviceServerBase.mass_inform
(msg)Send an inform message to all clients. DeviceServerBase.next
()DeviceServerBase.on_client_connect
(**kwargs)Called after client connection is established. DeviceServerBase.on_client_disconnect
(**kwargs)Called before a client connection is closed. DeviceServerBase.on_message
(client_conn, msg)Dummy implementation of on_message required by KATCPServer. DeviceServerBase.reply
(connection, reply, …)Send an asynchronous reply to an earlier request. DeviceServerBase.reply_inform
(connection, …)Send an inform as part of the reply to an earlier request. DeviceServerBase.running
()Whether the server is running. DeviceServerBase.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False DeviceServerBase.set_concurrency_options
([…])Set concurrency options for this device server. DeviceServerBase.set_ioloop
([ioloop])Set the tornado IOLoop to use. DeviceServerBase.start
([timeout])Start the server in a new thread. DeviceServerBase.stop
([timeout])Stop a running server (from another thread). DeviceServerBase.sync_with_ioloop
([timeout])Block for ioloop to complete a loop if called from another thread. DeviceServerBase.wait_running
([timeout])Wait until the server is running -
create_log_inform
(level_name, msg, name, timestamp=None)¶ Create a katcp logging inform message.
Usually this will be called from inside a DeviceLogger object, but it is also used by the methods in this class when errors need to be reported to the client.
-
handle_inform
(connection, msg)¶ Dispatch an inform message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The inform message to process.
-
handle_message
(client_conn, msg)¶ Handle messages of all types from clients.
Parameters: client_conn : ClientConnection object
The client connection the message was from.
msg : Message object
The message to process.
-
handle_reply
(connection, msg)¶ Dispatch a reply message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The reply message to process.
-
handle_request
(connection, msg)¶ Dispatch a request message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The request message to process.
Returns: done_future : Future or None
Returns Future for async request handlers that will resolve when done, or None for sync request handlers once they have completed.
-
inform
(connection, msg)¶ Send an inform message to a particular client.
Should only be used for asynchronous informs. Informs that are part of the response to a request should use
reply_inform()
so that the message identifier from the original request can be attached to the inform.Parameters: connection : ClientConnection object
The client to send the message to.
msg : Message object
The inform message to send.
-
join
(timeout=None)¶ Rejoin the server thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for the thread to finish.
-
mass_inform
(msg)¶ Send an inform message to all clients.
Parameters: msg : Message object
The inform message to send.
-
on_client_connect
(**kwargs)¶ Called after client connection is established.
Subclasses should override if they wish to send clients message or perform house-keeping at this point.
Parameters: conn : ClientConnection object
The client connection that has been successfully established.
Returns: Future that resolves when the device is ready to accept messages. :
-
on_client_disconnect
(**kwargs)¶ Called before a client connection is closed.
Subclasses should override if they wish to send clients message or perform house-keeping at this point. The server cannot guarantee this will be called (for example, the client might drop the connection). The message parameter contains the reason for the disconnection.
Parameters: conn : ClientConnection object
Client connection being disconnected.
msg : str
Reason client is being disconnected.
connection_valid : boolean
True if connection is still open for sending, False otherwise.
Returns: Future that resolves when the client connection can be closed. :
-
on_message
(client_conn, msg)¶ Dummy implementation of on_message required by KATCPServer.
Will be replaced by a handler with the appropriate concurrency semantics when set_concurrency_options is called (defaults are set in __init__()).
-
reply
(connection, reply, orig_req)¶ Send an asynchronous reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the reply to.
reply : Message object
The reply message to send.
orig_req : Message object
The request message being replied to. The reply message’s id is overridden with the id from orig_req before the reply is sent.
-
reply_inform
(connection, inform, orig_req)¶ Send an inform as part of the reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the inform to.
inform : Message object
The inform message to send.
orig_req : Message object
The request message being replied to. The inform message’s id is overridden with the id from orig_req before the inform is sent.
-
running
()¶ Whether the server is running.
-
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
set_concurrency_options
(thread_safe=True, handler_thread=True)¶ Set concurrency options for this device server. Must be called before
start()
.Parameters: thread_safe : bool
If True, make the server public methods thread safe. Incurs performance overhead.
handler_thread : bool
Can only be set if thread_safe is True. Handle all requests (even from different clients) in a separate, single, request-handling thread. Blocking request handlers will prevent the server from handling new requests from any client, but sensor strategies should still function. This more or less mimics the behaviour of a server in library versions before 0.6.0.
-
set_ioloop
(ioloop=None)¶ Set the tornado IOLoop to use.
Sets the tornado.ioloop.IOLoop instance to use, defaulting to IOLoop.current(). If set_ioloop() is never called the IOLoop is started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called.
-
start
(timeout=None)¶ Start the server in a new thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for server thread to start.
-
stop
(timeout=1.0)¶ Stop a running server (from another thread).
Parameters: timeout : float, optional
Seconds to wait for server to have started.
Returns: stopped : thread-safe Future
Resolves when the server is stopped
-
sync_with_ioloop
(timeout=None)¶ Block for ioloop to complete a loop if called from another thread.
Returns a future if called from inside the ioloop.
Raises concurrent.futures.TimeoutError if timed out while blocking.
-
wait_running
(timeout=None)¶ Wait until the server is running
-
DeviceLogger¶
-
class
katcp.
DeviceLogger
(device_server, root_logger='root', python_logger=None)¶ Object for logging messages from a DeviceServer.
Log messages are logged at a particular level and under a particular name. Names use dotted notation to form a virtual hierarchy of loggers with the device.
Parameters: device_server : DeviceServerBase object
The device server this logger should use for sending out logs.
root_logger : str
The name of the root logger.
Methods
DeviceLogger.debug
(msg, *args, **kwargs)Log a debug message. DeviceLogger.error
(msg, *args, **kwargs)Log an error message. DeviceLogger.fatal
(msg, *args, **kwargs)Log a fatal error message. DeviceLogger.info
(msg, *args, **kwargs)Log an info message. DeviceLogger.level_from_name
(level_name)Return the level constant for a given name. DeviceLogger.level_name
([level])Return the name of the given level value. DeviceLogger.log
(level, msg, *args, **kwargs)Log a message and inform all clients. DeviceLogger.log_to_python
(logger, msg)Log a KATCP logging message to a Python logger. DeviceLogger.next
()DeviceLogger.set_log_level
(level)Set the logging level. DeviceLogger.set_log_level_by_name
(level_name)Set the logging level using a level name. DeviceLogger.trace
(msg, *args, **kwargs)Log a trace message. DeviceLogger.warn
(msg, *args, **kwargs)Log an warning message. -
debug
(msg, *args, **kwargs)¶ Log a debug message.
-
error
(msg, *args, **kwargs)¶ Log an error message.
-
fatal
(msg, *args, **kwargs)¶ Log a fatal error message.
-
info
(msg, *args, **kwargs)¶ Log an info message.
-
level_from_name
(level_name)¶ Return the level constant for a given name.
If the level_name is not known, raise a ValueError.
Parameters: level_name : str or bytes
The logging level name whose logging level constant to retrieve.
Returns: level : logging level constant
The logging level constant associated with the name.
-
level_name
(level=None)¶ Return the name of the given level value.
If level is None, return the name of the current level.
Parameters: level : logging level constant
The logging level constant whose name to retrieve.
Returns: level_name : str
The name of the logging level.
-
log
(level, msg, *args, **kwargs)¶ Log a message and inform all clients.
Parameters: level : logging level constant
The level to log the message at.
msg : str
The text format for the log message.
args : list of objects
Arguments to pass to log format string. Final message text is created using: msg % args.
kwargs : additional keyword parameters
Allowed keywords are ‘name’ and ‘timestamp’. The name is the name of the logger to log the message to. If not given the name defaults to the root logger. The timestamp is a float in seconds. If not given the timestamp defaults to the current time.
-
classmethod
log_to_python
(logger, msg)¶ Log a KATCP logging message to a Python logger.
Parameters: logger : logging.Logger object
The Python logger to log the given message to.
msg : Message object
The #log message to create a log entry from.
-
set_log_level
(level)¶ Set the logging level.
Parameters: level : logging level constant
The value to set the logging level to.
-
set_log_level_by_name
(level_name)¶ Set the logging level using a level name.
Parameters: level_name : str or bytes
The name of the logging level.
-
trace
(msg, *args, **kwargs)¶ Log a trace message.
-
warn
(msg, *args, **kwargs)¶ Log an warning message.
-
Sensor¶
-
class
katcp.
Sensor
(sensor_type, name, description=None, units=None, params=None, default=None, initial_status=None)¶ Instantiate a new sensor object.
Subclasses will usually pass in a fixed sensor_type which should be one of the sensor type constants. The list params if set will have its values formatted by the type formatter for the given sensor type.
Note
The LRU sensor type was deprecated in katcp 0.4.
Note
The ADDRESS sensor type was added in katcp 0.4.
Parameters: sensor_type : Sensor type constant
The type of sensor.
name : str
The name of the sensor.
description : str, optional
A short description of the sensor.
units : str, optional
The units of the sensor value. May be the empty string if there are no applicable units.
params : list, optional
Additional parameters, dependent on the type of sensor:
- For
INTEGER
andFLOAT
the list is optional. If provided, it should have two items, providing the minimum and maximum that define the range of the sensor value, respectively. The type of each item must be int, or float. - For
DISCRETE
the list is required, and must contain all possible values the sensor may take. There must be at least one item. The type of each item must be str or bytes. - For all other types, params should be omitted.
default : object, optional
An initial value for the sensor. By default this is determined by the sensor type. For
INTEGER
andFLOAT
sensors, if no default is provided, but valid minimum and maximum parameters are, the default will be set to the minimum.initial_status : int enum or None, optional
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
Methods
Sensor.address
(name[, description, unit, …])Instantiate a new IP address sensor object. Sensor.attach
(observer)Attach an observer to this sensor. Sensor.boolean
(name[, description, unit, …])Instantiate a new boolean sensor object. Sensor.detach
(observer)Detach an observer from this sensor. Sensor.discrete
(name[, description, unit, …])Instantiate a new discrete sensor object. Sensor.float
(name[, description, unit, …])Instantiate a new float sensor object. Sensor.format_reading
(reading[, major])Format sensor reading as (timestamp, status, value) tuple of byte strings. Sensor.integer
(name[, description, unit, …])Instantiate a new integer sensor object. Sensor.lru
(name[, description, unit, …])Instantiate a new lru sensor object. Sensor.notify
(reading)Notify all observers of changes to this sensor. Sensor.parse_params
(sensor_type, …[, major])Parse KATCP formatted parameters into Python values. Sensor.parse_type
(type_string)Parse KATCP formatted type code into Sensor type constant. Sensor.parse_value
(s_value[, katcp_major])Parse a value from a byte string. Sensor.read
()Read the sensor and return a (timestamp, status, value) tuple. Sensor.read_formatted
([major])Read the sensor and return a (timestamp, status, value) tuple. Sensor.set
(timestamp, status, value)Set the current value of the sensor. Sensor.set_formatted
(raw_timestamp, …[, major])Set the current value of the sensor. Sensor.set_value
(value[, status, timestamp, …])Check and then set the value of the sensor. Sensor.status
()Read the current sensor status. Sensor.string
(name[, description, unit, …])Instantiate a new string sensor object. Sensor.timestamp
(name[, description, unit, …])Instantiate a new timestamp sensor object. Sensor.value
()Read the current sensor value. -
classmethod
address
(name, description=None, unit='', default=None, initial_status=None)¶ Instantiate a new IP address sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit : str
The units of the sensor value. May be the empty string if there are no applicable units.
default : (string, int)
An initial value for the sensor. Tuple containing (host, port). default is (“0.0.0.0”, None)
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
attach
(observer)¶ Attach an observer to this sensor.
The observer must support a call to observer.update(sensor, reading), where sensor is the sensor object and reading is a (timestamp, status, value) tuple for this update (matching the return value of the
read()
method).Parameters: observer : object
Object with an .update(sensor, reading) method that will be called when the sensor value is set
-
classmethod
boolean
(name, description=None, unit='', default=None, initial_status=None)¶ Instantiate a new boolean sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit : str
The units of the sensor value. May be the empty string if there are no applicable units.
default : bool
An initial value for the sensor. Defaults to False.
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
detach
(observer)¶ Detach an observer from this sensor.
Parameters: observer : object
The observer to remove from the set of observers notified when the sensor value is set.
-
classmethod
discrete
(name, description=None, unit='', params=None, default=None, initial_status=None)¶ Instantiate a new discrete sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit : str
The units of the sensor value. May be the empty string if there are no applicable units.
params : [str]
Sequence of all allowable discrete sensor states
default : str
An initial value for the sensor. Defaults to the first item of params
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
classmethod
float
(name, description=None, unit='', params=None, default=None, initial_status=None)¶ Instantiate a new float sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit : str
The units of the sensor value. May be the empty string if there are no applicable units.
params : list
[min, max] – minimum and maximum values of the sensor
default : float
An initial value for the sensor. Defaults to 0.0.
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
format_reading
(reading, major=5)¶ Format sensor reading as (timestamp, status, value) tuple of byte strings.
All values are strings formatted as specified in the Sensor Type Formats in the katcp specification.
Parameters: reading :
Reading
objectSensor reading as returned by
read()
major : int
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Returns: timestamp : bytes
KATCP formatted timestamp byte string
status : bytes
KATCP formatted sensor status byte string
value : bytes
KATCP formatted sensor value byte string
Notes
Should only be used for a reading obtained from the same sensor.
-
classmethod
integer
(name, description=None, unit='', params=None, default=None, initial_status=None)¶ Instantiate a new integer sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit : str
The units of the sensor value. May be the empty string if there are no applicable units.
params : list
[min, max] – minimum and maximum values of the sensor
default : int
An initial value for the sensor. Defaults to 0.
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
classmethod
lru
(name, description=None, unit='', default=None, initial_status=None)¶ Instantiate a new lru sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit : str
The units of the sensor value. May be the empty string if there are no applicable units.
default : enum, Sensor.LRU_*
An initial value for the sensor. Defaults to self.LRU_NOMINAL
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
notify
(reading)¶ Notify all observers of changes to this sensor.
-
classmethod
parse_params
(sensor_type, formatted_params, major=5)¶ Parse KATCP formatted parameters into Python values.
Parameters: sensor_type : Sensor type constant
The type of sensor the parameters are for.
formatted_params : list of byte strings
The formatted parameters that should be parsed.
major : int
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Returns: params : list of objects
The parsed parameters.
-
classmethod
parse_type
(type_string)¶ Parse KATCP formatted type code into Sensor type constant.
Parameters: type_string : str
KATCP formatted type code.
Returns: sensor_type : Sensor type constant
The corresponding Sensor type constant.
-
parse_value
(s_value, katcp_major=5)¶ Parse a value from a byte string.
Parameters: s_value : bytes
A byte string value to attempt to convert to a value for the sensor.
Returns: value : object
A value of a type appropriate to the sensor.
-
read
()¶ Read the sensor and return a (timestamp, status, value) tuple.
Returns: reading :
Reading
objectSensor reading as a (timestamp, status, value) tuple.
-
read_formatted
(major=5)¶ Read the sensor and return a (timestamp, status, value) tuple.
All values are byte strings formatted as specified in the Sensor Type Formats in the katcp specification.
Parameters: major : int
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Returns: timestamp : bytes
KATCP formatted timestamp byte string
status : bytes
KATCP formatted sensor status byte string
value : bytes
KATCP formatted sensor value byte string
-
set
(timestamp, status, value)¶ Set the current value of the sensor.
Parameters: timestamp : float in seconds
The time at which the sensor value was determined.
status : Sensor status constant
Whether the value represents an error condition or not.
value : object
The value of the sensor (the type should be appropriate to the sensor’s type).
-
set_formatted
(raw_timestamp, raw_status, raw_value, major=5)¶ Set the current value of the sensor.
Parameters: raw_timestamp : bytes
KATCP formatted timestamp byte string
raw_status : bytes
KATCP formatted sensor status byte string
raw_value : bytes
KATCP formatted sensor value byte string
major : int, default = 5
KATCP major version to use for interpreting the raw values
-
set_value
(value, status=1, timestamp=None, major=5)¶ Check and then set the value of the sensor.
Parameters: value : object
Value of the appropriate type for the sensor.
status : Sensor status constant
Whether the value represents an error condition or not.
timestamp : float in seconds or None
The time at which the sensor value was determined. Uses current time if None.
major : int
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
-
status
()¶ Read the current sensor status.
Returns: status : enum (int)
The status of the sensor, one of the keys in Sensor.STATUSES
-
classmethod
string
(name, description=None, unit='', default=None, initial_status=None)¶ Instantiate a new string sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit : str
The units of the sensor value. May be the empty string if there are no applicable units.
default : string
An initial value for the sensor. Defaults to the empty string.
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
classmethod
timestamp
(name, description=None, unit='', default=None, initial_status=None)¶ Instantiate a new timestamp sensor object.
Parameters: name : str
The name of the sensor.
description : str
A short description of the sensor.
unit: str :
The units of the sensor value. For timestamp sensor may only be the empty string.
default : string
An initial value for the sensor in seconds since the Unix Epoch. Defaults to 0.
initial_status : int enum or None
An initial status for the sensor. If None, defaults to Sensor.UNKNOWN. initial_status must be one of the keys in Sensor.STATUSES
-
value
()¶ Read the current sensor value.
Returns: value : object
The value of the sensor (the type will be appropriate to the sensor’s type).
- For
Exceptions¶
-
class
katcp.
FailReply
¶ Raised by request handlers to indicate a failure.
A custom exception which, when thrown in a request handler, causes DeviceServerBase to send a fail reply with the specified fail message, bypassing the generic exception handling, which would send a fail reply with a full traceback.
Examples
>>> class MyDevice(DeviceServer): ... def request_myreq(self, req, msg): ... raise FailReply("This request always fails.") ...
-
class
katcp.
AsyncReply
¶ Raised by a request handlers to indicate it will reply later.
A custom exception which, when thrown in a request handler, indicates to DeviceServerBase that no reply has been returned by the handler but that the handler has arranged for a reply message to be sent at a later time.
Examples
>>> class MyDevice(DeviceServer): ... def request_myreq(self, req, msg): ... self.callback_client.request( ... Message.request("otherreq"), ... reply_cb=self._send_reply, ... ) ... raise AsyncReply() ...
-
class
katcp.
KatcpDeviceError
¶ Raised by KATCP servers when errors occur.
Changed in version 0.1: Deprecated in 0.1. Servers should not raise errors if communication with a client fails – errors are simply logged instead.
High Level Clients¶
KATCPClientResource¶
-
class
katcp.
KATCPClientResource
(resource_spec, parent=None, logger=<logging.Logger object>)¶ Class managing a client connection to a single KATCP resource
Inspects the KATCP interface of the resources, exposing sensors and requests as per the
katcp.resource.KATCPResource
API. Can also operate without exposingMethods
KATCPClientResource.drop_sampling_strategy
(…)Drop the sampling strategy for the named sensor from the cache KATCPClientResource.inspecting_client_factory
(…)Return an instance of ReplyWrappedInspectingClientAsync
or similarKATCPClientResource.is_active
()KATCPClientResource.is_connected
()Indication of the connection state KATCPClientResource.list_sensors
([filter, …])List sensors available on this resource matching certain criteria. KATCPClientResource.next
()KATCPClientResource.set_active
(active)KATCPClientResource.set_ioloop
([ioloop])Set the tornado ioloop to use KATCPClientResource.set_sampling_strategies
(…)Set a strategy for all sensors matching the filter, including unseen sensors The strategy should persist across sensor disconnect/reconnect. KATCPClientResource.set_sampling_strategy
(…)Set a strategy for a sensor even if it is not yet known. KATCPClientResource.set_sensor_listener
(**kwargs)Set a sensor listener for a sensor even if it is not yet known The listener registration should persist across sensor disconnect/reconnect. KATCPClientResource.start
()Start the client and connect KATCPClientResource.stop
()KATCPClientResource.until_not_synced
([timeout])Convenience method to wait (with Future) until client is not synced KATCPClientResource.until_state
(state[, timeout])Future that resolves when a certain client state is attained KATCPClientResource.until_stopped
([timeout])Return future that resolves when the inspecting client has stopped KATCPClientResource.until_synced
([timeout])Convenience method to wait (with Future) until client is synced KATCPClientResource.wait
(**kwargs)Wait for a sensor in this resource to satisfy a condition. KATCPClientResource.wait_connected
([timeout])Future that resolves when the state is not ‘disconnected’. -
MAX_LOOP_LATENCY
= 0.03¶ When doing potentially tight loops in coroutines yield tornado.gen.moment after this much time. This is a suggestion for methods to use.
-
drop_sampling_strategy
(sensor_name)¶ Drop the sampling strategy for the named sensor from the cache
Calling
set_sampling_strategy()
requires the requested strategy to be memorised so that it can automatically be reapplied. This method causes the strategy to be forgotten. There is no change to the current strategy. No error is raised if there is no strategy to drop.Parameters: sensor_name : str
Name of the sensor
-
inspecting_client_factory
(host, port, ioloop_set_to)¶ Return an instance of
ReplyWrappedInspectingClientAsync
or similarProvided to ease testing. Dynamically overriding this method after instantiation but before start() is called allows for deep brain surgery. See
katcp.fake_clients.fake_inspecting_client_factory
-
is_connected
()¶ Indication of the connection state
Returns True if state is not “disconnected”, i.e “syncing” or “synced”
-
list_sensors
(filter='', strategy=False, status='', use_python_identifiers=True, tuple=False, refresh=False)¶ List sensors available on this resource matching certain criteria.
Parameters: filter : string, optional
Filter each returned sensor’s name against this regexp if specified. To ease the dichotomy between Python identifier names and actual sensor names, the default is to search on Python identifier names rather than KATCP sensor names, unless use_python_identifiers below is set to False. Note that the sensors of subordinate KATCPResource instances may have inconsistent names and Python identifiers, better to always search on Python identifiers in this case.
strategy : {False, True}, optional
Only list sensors with a set strategy if True
status : string, optional
Filter each returned sensor’s status against this regexp if given
use_python_identifiers : {True, False}, optional
Match on python identifiers even the the KATCP name is available.
tuple : {True, False}, optional, Default: False
Return backwards compatible tuple instead of SensorResultTuples
refresh : {True, False}, optional, Default: False
If set the sensor values will be refreshed with get_value before returning the results.
Returns: sensors : list of SensorResultTuples, or list of tuples
List of matching sensors presented as named tuples. The object field is the
KATCPSensor
object associated with the sensor. Note that the name of the object may not match name if it originates from a subordinate device.
-
set_ioloop
(ioloop=None)¶ Set the tornado ioloop to use
Defaults to tornado.ioloop.IOLoop.current() if set_ioloop() is not called or if ioloop=None. Must be called before start()
-
set_sampling_strategies
(**kwargs)¶ Set a strategy for all sensors matching the filter, including unseen sensors The strategy should persist across sensor disconnect/reconnect.
- filter : str
- Filter for sensor names
- strategy_and_params : seq of str or str
- As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: done : tornado Future
Resolves when done
-
set_sampling_strategy
(**kwargs)¶ Set a strategy for a sensor even if it is not yet known. The strategy should persist across sensor disconnect/reconnect.
- sensor_name : str
- Name of the sensor
- strategy_and_params : seq of str or str
- As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: done : tornado Future
Resolves when done
-
set_sensor_listener
(**kwargs)¶ Set a sensor listener for a sensor even if it is not yet known The listener registration should persist across sensor disconnect/reconnect.
- sensor_name : str
- Name of the sensor
- listener : callable
- Listening callable that will be registered on the named sensor when it becomes
available. Callable as for
KATCPSensor.register_listener()
-
start
()¶ Start the client and connect
-
until_not_synced
(timeout=None)¶ Convenience method to wait (with Future) until client is not synced
-
until_state
(state, timeout=None)¶ Future that resolves when a certain client state is attained
Parameters: state : str
Desired state, one of (“disconnected”, “syncing”, “synced”)
timeout: float :
Timeout for operation in seconds.
-
until_stopped
(timeout=None)¶ Return future that resolves when the inspecting client has stopped
See the DeviceClient.until_stopped docstring for parameter definitions and more info.
-
until_synced
(timeout=None)¶ Convenience method to wait (with Future) until client is synced
-
wait
(**kwargs)¶ Wait for a sensor in this resource to satisfy a condition.
Parameters: sensor_name : string
The name of the sensor to check
condition_or_value : obj or callable, or seq of objs or callables
If obj, sensor.value is compared with obj. If callable, condition_or_value(reading) is called, and must return True if its condition is satisfied. Since the reading is passed in, the value, status, timestamp or received_timestamp attributes can all be used in the check.
timeout : float or None
The timeout in seconds (None means wait forever)
Returns: This command returns a tornado Future that resolves with True when the :
sensor value satisfies the condition, or False if the condition is :
still not satisfied after a given timeout period. :
Raises: :class:`KATCPSensorError` :
If the sensor does not have a strategy set, or if the named sensor is not present
-
wait_connected
(timeout=None)¶ Future that resolves when the state is not ‘disconnected’.
-
KATCPClientResourceContainer¶
-
class
katcp.
KATCPClientResourceContainer
(resources_spec, logger=<logging.Logger object>)¶ Class for containing multiple
KATCPClientResource
instances.Provides aggregate sensor and req attributes containing the union of all the sensors in requests in the contained resources. Names are prefixed with <resname>_, where <resname> is the name of the resource to which the sensor / request belongs except for aggregate sensors that starts with
agg_
.Methods
KATCPClientResourceContainer.add_child_resource_client
(…)Add a resource client to the container and start the resource connection KATCPClientResourceContainer.add_group
(…)Add a new ClientGroup
to container groups member.KATCPClientResourceContainer.client_resource_factory
(…)Return an instance of KATCPClientResource
or similarKATCPClientResourceContainer.is_active
()KATCPClientResourceContainer.is_connected
()Indication of the connection state of all children KATCPClientResourceContainer.list_sensors
([…])List sensors available on this resource matching certain criteria. KATCPClientResourceContainer.next
()KATCPClientResourceContainer.set_active
(active)KATCPClientResourceContainer.set_ioloop
([ioloop])Set the tornado ioloop to use KATCPClientResourceContainer.set_sampling_strategies
(…)Set sampling strategies for filtered sensors - these sensors have to exists. KATCPClientResourceContainer.set_sampling_strategy
(…)Set sampling strategies for the specific sensor - this sensor has to exist KATCPClientResourceContainer.set_sensor_listener
(…)Set listener for the specific sensor - this sensor has to exists. KATCPClientResourceContainer.start
()Start and connect all the subordinate clients KATCPClientResourceContainer.stop
()Stop all child resources KATCPClientResourceContainer.until_all_children_in_state
(…)Return a tornado Future; resolves when all clients are in specified state KATCPClientResourceContainer.until_any_child_in_state
(state)Return a tornado Future; resolves when any client is in specified state KATCPClientResourceContainer.until_not_synced
(…)Return a tornado Future; resolves when any subordinate client is not synced KATCPClientResourceContainer.until_stopped
([…])Return dict of futures that resolve when each child resource has stopped KATCPClientResourceContainer.until_synced
(…)Return a tornado Future; resolves when all subordinate clients are synced KATCPClientResourceContainer.wait
(…[, timeout])Wait for a sensor in this resource to satisfy a condition. -
add_child_resource_client
(res_name, res_spec)¶ Add a resource client to the container and start the resource connection
-
add_group
(group_name, group_client_names)¶ Add a new
ClientGroup
to container groups member.Add the group named group_name with sequence of client names to the container groups member. From there it will be wrapped appropriately in the higher-level thread-safe container.
-
client_resource_factory
(res_spec, parent, logger)¶ Return an instance of
KATCPClientResource
or similarProvided to ease testing. Overriding this method allows deep brain surgery. See
katcp.fake_clients.fake_KATCP_client_resource_factory()
-
is_connected
()¶ Indication of the connection state of all children
-
list_sensors
(filter='', strategy=False, status='', use_python_identifiers=True, tuple=False, refresh=False)¶ List sensors available on this resource matching certain criteria.
Parameters: filter : string, optional
Filter each returned sensor’s name against this regexp if specified. To ease the dichotomy between Python identifier names and actual sensor names, the default is to search on Python identifier names rather than KATCP sensor names, unless use_python_identifiers below is set to False. Note that the sensors of subordinate KATCPResource instances may have inconsistent names and Python identifiers, better to always search on Python identifiers in this case.
strategy : {False, True}, optional
Only list sensors with a set strategy if True
status : string, optional
Filter each returned sensor’s status against this regexp if given
use_python_identifiers : {True, False}, optional
Match on python identifiers even the the KATCP name is available.
tuple : {True, False}, optional, Default: False
Return backwards compatible tuple instead of SensorResultTuples
refresh : {True, False}, optional, Default: False
If set the sensor values will be refreshed with get_value before returning the results.
Returns: sensors : list of SensorResultTuples, or list of tuples
List of matching sensors presented as named tuples. The object field is the
KATCPSensor
object associated with the sensor. Note that the name of the object may not match name if it originates from a subordinate device.
-
set_ioloop
(ioloop=None)¶ Set the tornado ioloop to use
Defaults to tornado.ioloop.IOLoop.current() if set_ioloop() is not called or if ioloop=None. Must be called before start()
-
set_sampling_strategies
(**kwargs)¶ Set sampling strategies for filtered sensors - these sensors have to exists.
-
set_sampling_strategy
(**kwargs)¶ Set sampling strategies for the specific sensor - this sensor has to exist
-
set_sensor_listener
(**kwargs)¶ Set listener for the specific sensor - this sensor has to exists.
-
start
()¶ Start and connect all the subordinate clients
-
stop
()¶ Stop all child resources
-
until_all_children_in_state
(**kwargs)¶ Return a tornado Future; resolves when all clients are in specified state
-
until_any_child_in_state
(state, timeout=None)¶ Return a tornado Future; resolves when any client is in specified state
-
until_not_synced
(**kwargs)¶ Return a tornado Future; resolves when any subordinate client is not synced
-
until_stopped
(timeout=None)¶ Return dict of futures that resolve when each child resource has stopped
See the DeviceClient.until_stopped docstring for parameter definitions and more info.
-
until_synced
(**kwargs)¶ Return a tornado Future; resolves when all subordinate clients are synced
-
wait
(sensor_name, condition_or_value, timeout=5)¶ Wait for a sensor in this resource to satisfy a condition.
Parameters: sensor_name : string
The name of the sensor to check
condition_or_value : obj or callable, or seq of objs or callables
If obj, sensor.value is compared with obj. If callable, condition_or_value(reading) is called, and must return True if its condition is satisfied. Since the reading is passed in, the value, status, timestamp or received_timestamp attributes can all be used in the check.
timeout : float or None
The timeout in seconds (None means wait forever)
Returns: This command returns a tornado Future that resolves with True when the :
sensor value satisfies the condition, or False if the condition is :
still not satisfied after a given timeout period. :
Raises: :class:`KATCPSensorError` :
If the sensor does not have a strategy set, or if the named sensor is not present
-
Message Parsing¶
Message¶
-
class
katcp.
Message
(mtype, name, arguments=None, mid=None)¶ Represents a KAT device control language message.
Parameters: mtype : Message type constant
The message type (request, reply or inform).
name : str
The message name.
arguments : list of objects (float, int, bool, bytes, or str)
The message arguments.
mid : str or bytes (digits only), int, or None
The message identifier. Replies and informs that are part of the reply to a request should have the same id as the request did.
Methods
Message.copy
()Return a shallow copy of the message object and its arguments. Message.format_argument
(arg)Format a Message argument to a byte string Message.inform
(name, *args, **kwargs)Helper method for creating inform messages. Message.reply
(name, *args, **kwargs)Helper method for creating reply messages. Message.reply_inform
(req_msg, *args)Helper method for creating inform messages in reply to a request. Message.reply_ok
()Return True if this is a reply and its first argument is ‘ok’. Message.reply_to_request
(req_msg, *args)Helper method for creating reply messages to a specific request. Message.request
(name, *args, **kwargs)Helper method for creating request messages. -
copy
()¶ Return a shallow copy of the message object and its arguments.
Returns: msg : Message
A copy of the message object.
-
format_argument
(arg)¶ Format a Message argument to a byte string
-
classmethod
inform
(name, *args, **kwargs)¶ Helper method for creating inform messages.
Parameters: name : str
The name of the message.
args : list of objects (float, int, bool, bytes, or str)
The message arguments.
Keyword Arguments: mid : str or bytes (digits only), int, or None
Message ID to use or None (default) for no Message ID
-
classmethod
reply
(name, *args, **kwargs)¶ Helper method for creating reply messages.
Parameters: name : str
The name of the message.
args : list of objects (float, int, bool, bytes, or str)
The message arguments.
Keyword Arguments: mid : str or bytes (digits only), int, or None
Message ID to use or None (default) for no Message ID
-
classmethod
reply_inform
(req_msg, *args)¶ Helper method for creating inform messages in reply to a request.
Copies the message name and message identifier from request message.
Parameters: req_msg : katcp.core.Message instance
The request message that this inform if in reply to
args : list of objects (float, int, bool, bytes, or str)
The message arguments except name
-
reply_ok
()¶ Return True if this is a reply and its first argument is ‘ok’.
-
classmethod
reply_to_request
(req_msg, *args)¶ Helper method for creating reply messages to a specific request.
Copies the message name and message identifier from request message.
Parameters: req_msg : katcp.core.Message instance
The request message that this inform if in reply to
args : list of objects (float, int, bool, bytes, or str)
The message arguments.
-
classmethod
request
(name, *args, **kwargs)¶ Helper method for creating request messages.
Parameters: name : str
The name of the message.
args : list of objects (float, int, bool, bytes, or str)
The message arguments.
Keyword Arguments: mid : str or bytes (digits only), int, or None
Message ID to use or None (default) for no Message ID
-
MessageParser¶
-
class
katcp.
MessageParser
¶ Parses lines into Message objects.
Methods
MessageParser.parse
(line)Parse a line, return a Message. -
parse
(line)¶ Parse a line, return a Message.
Parameters: line : bytes
The line to parse (should not contain the terminating newline or carriage return).
Returns: msg : Message object
The resulting Message.
-
Other¶
DeviceMetaclass¶
-
class
katcp.
DeviceMetaclass
(name, bases, dct)¶ Metaclass for DeviceServer and DeviceClient classes.
Collects up methods named request_* and adds them to a dictionary of supported methods on the class. All request_* methods must have a doc string so that help can be generated. The same is done for inform_* and reply_* methods.
Methods
DeviceMetaclass.check_protocol
(handler)Return False if handler should be filtered DeviceMetaclass.mro
()return a type’s method resolution order -
check_protocol
(handler)¶ Return False if handler should be filtered
-
Kattypes¶
Utilities for dealing with KATCP types.
-
class
katcp.kattypes.
Address
(default=None, optional=False, multiple=False)¶ Bases:
katcp.kattypes.KatcpType
The KATCP address type.
Note
The address type was added in katcp 0.4.
Methods
Address.check
(value, major)Check whether the value is valid. Address.decode
(value, major)Address.encode
(value, major)Address.get_default
()Return the default value. Address.next
()Address.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Address.unpack
(packed_value[, major])Parse a KATCP parameter into an object.
-
class
katcp.kattypes.
Bool
(default=None, optional=False, multiple=False)¶ Bases:
katcp.kattypes.KatcpType
The KATCP boolean type.
Methods
Bool.check
(value, major)Check whether the value is valid. Bool.decode
(value, major)Bool.encode
(value, major)Bool.get_default
()Return the default value. Bool.next
()Bool.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Bool.unpack
(packed_value[, major])Parse a KATCP parameter into an object.
-
class
katcp.kattypes.
Discrete
(values, case_insensitive=False, **kwargs)¶ Bases:
katcp.kattypes.Str
The KATCP discrete type.
Parameters: values : iterable of str
List of the values the discrete type may accept.
case_insensitive : bool
Whether case-insensitive value matching should be used.
Methods
Discrete.check
(value, major)Check whether the value in the set of allowed values. Discrete.decode
(value, major)Discrete.encode
(value, major)Discrete.get_default
()Return the default value. Discrete.next
()Discrete.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Discrete.unpack
(packed_value[, major])Parse a KATCP parameter into an object. -
check
(value, major)¶ Check whether the value in the set of allowed values.
Raise a ValueError if it is not.
-
-
class
katcp.kattypes.
DiscreteMulti
(values, all_keyword='all', separator=', ', **kwargs)¶ Bases:
katcp.kattypes.Discrete
Discrete type which can accept multiple values.
Its value is always a list.
Parameters: values : list of str
Set of allowed values.
all_keyword : str, optional
The string which represents the list of all allowed values.
separator : str, optional
The separator used in the packed value string.
Methods
DiscreteMulti.check
(value, major)Check that each item in the value list is in the allowed set. DiscreteMulti.decode
(value, major)DiscreteMulti.encode
(value, major)DiscreteMulti.get_default
()Return the default value. DiscreteMulti.next
()DiscreteMulti.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. DiscreteMulti.unpack
(packed_value[, major])Parse a KATCP parameter into an object. -
check
(value, major)¶ Check that each item in the value list is in the allowed set.
-
-
class
katcp.kattypes.
Float
(min=None, max=None, **kwargs)¶ Bases:
katcp.kattypes.KatcpType
The KATCP float type.
Parameters: min : float
The minimum allowed value. Ignored if not given.
max : float
The maximum allowed value. Ignored if not given.
Methods
Float.check
(value, major)Check whether the value is between the minimum and maximum. Float.decode
(value, major)Float.encode
(value, major)Float.get_default
()Return the default value. Float.next
()Float.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Float.unpack
(packed_value[, major])Parse a KATCP parameter into an object. -
check
(value, major)¶ Check whether the value is between the minimum and maximum.
Raise a ValueError if it is not.
-
-
class
katcp.kattypes.
Int
(min=None, max=None, **kwargs)¶ Bases:
katcp.kattypes.KatcpType
The KATCP integer type.
Parameters: min : int
The minimum allowed value. Ignored if not given.
max : int
The maximum allowed value. Ignored if not given.
Methods
Int.check
(value, major)Check whether the value is between the minimum and maximum. Int.decode
(value, major)Int.encode
(value, major)Int.get_default
()Return the default value. Int.next
()Int.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Int.unpack
(packed_value[, major])Parse a KATCP parameter into an object. -
check
(value, major)¶ Check whether the value is between the minimum and maximum.
Raise a ValueError if it is not.
-
-
class
katcp.kattypes.
KatcpType
(default=None, optional=False, multiple=False)¶ Bases:
future.types.newobject.newobject
Class representing a KATCP type.
Sub-classes should:
- Set the
name
attribute. - Implement the
encode()
method. - Implement the
decode()
method.
Parameters: default : object, optional
The default value for this type.
optional : boolean, optional
Whether the value is allowed to be None.
multiple : boolean, optional
Whether multiple values of this type are expected. Must be the last type parameter if this is True.
Methods
KatcpType.check
(value, major)Check whether the value is valid. KatcpType.get_default
()Return the default value. KatcpType.next
()KatcpType.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. KatcpType.unpack
(packed_value[, major])Parse a KATCP parameter into an object. -
check
(value, major)¶ Check whether the value is valid.
Do nothing if the value is valid. Raise an exception if the value is not valid. Parameter major describes the KATCP major version to use when interpreting the validity of a value.
-
get_default
()¶ Return the default value.
Raise a ValueError if the value is not optional and there is no default.
Returns: default : object
The default value.
-
pack
(value, nocheck=False, major=5)¶ Return the value formatted as a KATCP parameter.
Parameters: value : object
The value to pack.
nocheck : bool, optional
Whether to check that the value is valid before packing it.
major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Returns: packed_value : bytes
The unescaped KATCP byte string representing the value.
-
unpack
(packed_value, major=5)¶ Parse a KATCP parameter into an object.
Parameters: packed_value : bytes
The unescaped KATCP byte string to parse into a value.
major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Returns: value : object
The value the KATCP string represented.
- Set the
-
class
katcp.kattypes.
Lru
(default=None, optional=False, multiple=False)¶ Bases:
katcp.kattypes.KatcpType
The KATCP lru type
Methods
Lru.check
(value, major)Check whether the value is valid. Lru.decode
(value, major)Lru.encode
(value, major)Lru.get_default
()Return the default value. Lru.next
()Lru.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Lru.unpack
(packed_value[, major])Parse a KATCP parameter into an object.
-
class
katcp.kattypes.
Parameter
(position, name, kattype, major)¶ Bases:
future.types.newobject.newobject
Wrapper for kattypes which holds parameter-specific information.
Parameters: position : int
The parameter’s position (starts at 1)
name : str
The parameter’s name (introspected)
kattype : KatcpType object
The parameter’s kattype
major : integer
Major version of KATCP to use when interpreting types
Methods
Parameter.next
()Parameter.pack
(value)Pack the parameter using its kattype. Parameter.unpack
(value)Unpack the parameter using its kattype. -
pack
(value)¶ Pack the parameter using its kattype.
Parameters: value : object
The value to pack
Returns: packed_value : str
The unescaped KATCP string representing the value.
-
unpack
(value)¶ Unpack the parameter using its kattype.
Parameters: packed_value : str
The unescaped KATCP string to unpack.
Returns: value : object
The unpacked value.
-
-
class
katcp.kattypes.
Regex
(regex, **kwargs)¶ Bases:
katcp.kattypes.Str
String type that checks values using a regular expression.
Parameters: regex : str or regular expression object
Regular expression that values should match.
Methods
Regex.check
(value, major)Check whether the value is valid. Regex.decode
(value, major)Regex.encode
(value, major)Regex.get_default
()Return the default value. Regex.next
()Regex.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Regex.unpack
(packed_value[, major])Parse a KATCP parameter into an object. -
check
(value, major)¶ Check whether the value is valid.
Do nothing if the value is valid. Raise an exception if the value is not valid. Parameter major describes the KATCP major version to use when interpreting the validity of a value.
-
-
class
katcp.kattypes.
Str
(default=None, optional=False, multiple=False)¶ Bases:
katcp.kattypes.KatcpType
The KATCP string type.
Notes
The behaviour of this type is subtly different between Python versions in order to ease the porting effort for users of this library. - Unpacked (decoded) values are native strings (bytes in PY2, Unicode in PY3). - Packed (encoded) values are always byte strings (in both PY2 and PY3), as this is what is sent on the wire.
UTF-8 encoding is used when converting between Unicode and byte strings. Thus ASCII values are fine, but arbitrary strings of bytes are not safe to use, and may raise an exception.
For convenience, non-text types can be encoded. The object is converted to a string, and then to bytes. This is a one-way operation - when that byte string is decoded the original type will not be recovered.
Methods
Str.check
(value, major)Check whether the value is valid. Str.decode
(value, major)Str.encode
(value, major)Str.get_default
()Return the default value. Str.next
()Str.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Str.unpack
(packed_value[, major])Parse a KATCP parameter into an object.
-
class
katcp.kattypes.
StrictTimestamp
(default=None, optional=False, multiple=False)¶ Bases:
katcp.kattypes.KatcpType
A timestamp that enforces the XXXX.YYY format for timestamps.
Methods
StrictTimestamp.check
(value, major)Check whether the value is positive. StrictTimestamp.decode
(value, major)StrictTimestamp.encode
(value, major)StrictTimestamp.get_default
()Return the default value. StrictTimestamp.next
()StrictTimestamp.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. StrictTimestamp.unpack
(packed_value[, major])Parse a KATCP parameter into an object. -
check
(value, major)¶ Check whether the value is positive.
Raise a ValueError if it is not.
-
-
class
katcp.kattypes.
Struct
(fmt, **kwargs)¶ Bases:
katcp.kattypes.KatcpType
KatcpType for parsing and packing values using the
struct
module.Parameters: fmt : str
Format to use for packing and unpacking values. It is passed directly into
struct.pack()
andstruct.unpack()
.Methods
Struct.check
(value, major)Check whether the value is valid. Struct.decode
(value, major)Struct.encode
(value, major)Struct.get_default
()Return the default value. Struct.next
()Struct.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Struct.unpack
(packed_value[, major])Parse a KATCP parameter into an object.
-
class
katcp.kattypes.
Timestamp
(default=None, optional=False, multiple=False)¶ Bases:
katcp.kattypes.KatcpType
The KATCP timestamp type.
Methods
Timestamp.check
(value, major)Check whether the value is valid. Timestamp.decode
(value, major)Timestamp.encode
(value, major)Timestamp.get_default
()Return the default value. Timestamp.next
()Timestamp.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. Timestamp.unpack
(packed_value[, major])Parse a KATCP parameter into an object.
-
class
katcp.kattypes.
TimestampOrNow
(default=None, optional=False, multiple=False)¶ Bases:
katcp.kattypes.Timestamp
KatcpType representing either a Timestamp or the special value for now.
Floats are encoded as for
katcp.kattypes.Timestamp
. The special value for now,katcp.kattypes.TimestampOrNow.NOW
, is encoded as the string “now”.Methods
TimestampOrNow.check
(value, major)Check whether the value is valid. TimestampOrNow.decode
(value, major)TimestampOrNow.encode
(value, major)TimestampOrNow.get_default
()Return the default value. TimestampOrNow.next
()TimestampOrNow.pack
(value[, nocheck, major])Return the value formatted as a KATCP parameter. TimestampOrNow.unpack
(packed_value[, major])Parse a KATCP parameter into an object.
-
katcp.kattypes.
async_make_reply
(*args, **kwargs)¶ Wrap future that will resolve with arguments needed by make_reply().
-
katcp.kattypes.
concurrent_reply
(handler)¶ Decorator for concurrent async request handlers
By default async request handlers that return a Future are serialised per-connection, i.e. until the most recent handler resolves its future, the next message will not be read from the client stream. A handler decorated with this decorator allows the next message to be read before it has resolved its future, allowing multiple requests from a single client to be handled concurrently. This is similar to raising AsyncReply.
Examples
>>> class MyDevice(DeviceServer): ... @return_reply(Int()) ... @concurrent_reply ... @tornado.gen.coroutine ... def request_myreq(self, req): ... '''A slow request''' ... result = yield self.slow_operation() ... raise tornado.gen.Return((req, result)) ...
-
katcp.kattypes.
has_katcp_protocol_flags
(protocol_flags)¶ Decorator; only include handler if server has these protocol flags
Useful for including default handler implementations for KATCP features that are only present when certain server protocol flags are set.
Examples
>>> class MyDevice(DeviceServer): ... '''This device server will expose ?myreq''' ... PROTOCOL_INFO = katcp.core.ProtocolFlags(5, 0, [ katcp.core.ProtocolFlags.MULTI_CLIENT]) ... ... @has_katcp_protocol_flags([katcp.core.ProtocolFlags.MULTI_CLIENT]) ... def request_myreq(self, req, msg): ... '''A request that requires multi-client support''' ... # Request handler implementation here. ... >>> class MySingleClientDevice(MyDevice): ... '''This device server will not expose ?myreq''' ... ... PROTOCOL_INFO = katcp.core.ProtocolFlags(5, 0, []) ...
-
katcp.kattypes.
inform
()¶ Decorator for inform handler methods.
The method being decorated should take arguments matching the list of types. The decorator will unpack the request message into the arguments.
Parameters: types : list of kattypes
The types of the request message parameters (in order). A type with multiple=True has to be the last type.
Keyword Arguments: include_msg : bool, optional
Pass the request message as the third parameter to the decorated request handler function (default is False).
major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Examples
>>> class MyDeviceClient(katcp.client.AsyncClient): ... @inform(Int(), Float()) ... def inform_myinf(self, my_int, my_float): ... '''Handle #myinf <my_int> <my_float> inform received from server''' ... # Call some code here that reacts to my_inf and my_float
-
katcp.kattypes.
make_reply
(msgname, types, arguments, major)¶ Helper method for constructing a reply message from a list or tuple.
Parameters: msgname : str
Name of the reply message.
types : list of kattypes
The types of the reply message parameters (in order).
arguments : list of objects
The (unpacked) reply message parameters.
major : integer
Major version of KATCP to use when packing types
-
katcp.kattypes.
minimum_katcp_version
(major, minor=0)¶ Decorator; exclude handler if server’s protocol version is too low
Useful for including default handler implementations for KATCP features that are only present in certain KATCP protocol versions
Examples
>>> class MyDevice(DeviceServer): ... '''This device server will expose ?myreq''' ... PROTOCOL_INFO = katcp.core.ProtocolFlags(5, 1) ... ... @minimum_katcp_version(5, 1) ... def request_myreq(self, req, msg): ... '''A request that should only be present for KATCP >v5.1''' ... # Request handler implementation here. ... >>> class MyOldDevice(MyDevice): ... '''This device server will not expose ?myreq''' ... ... PROTOCOL_INFO = katcp.core.ProtocolFlags(5, 0) ...
-
katcp.kattypes.
pack_types
(types, args, major)¶ Pack arguments according the the types list.
Parameters: types : sequence of kattypes
The types of the arguments (in order).
args : sequence of objects
The arguments to format.
major : integer
Major version of KATCP to use when packing types
Returns: packed_args : list
List of args after packing to byte strings
-
katcp.kattypes.
request
(*types, **options)¶ Decorator for request handler methods.
The method being decorated should take a req argument followed by arguments matching the list of types. The decorator will unpack the request message into the arguments.
Parameters: types : list of kattypes
The types of the request message parameters (in order). A type with multiple=True has to be the last type.
Keyword Arguments: include_msg : bool, optional
Pass the request message as the third parameter to the decorated request handler function (default is False).
major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Examples
>>> class MyDevice(DeviceServer): ... @request(Int(), Float(), Bool()) ... @return_reply(Int(), Float()) ... def request_myreq(self, req, my_int, my_float, my_bool): ... '''?myreq my_int my_float my_bool''' ... return ("ok", my_int + 1, my_float / 2.0) ... ... @request(Int(), include_msg=True) ... @return_reply(Bool()) ... def request_is_odd(self, req, msg, my_int): '''?is-odd <my_int>, reply '1' if <my_int> is odd, else 0''' ... req.inform('Checking oddity of %d' % my_int) ... return ("ok", my_int % 2) ...
-
katcp.kattypes.
request_timeout_hint
(timeout_hint)¶ Decorator; add recommended client timeout hint to a request for request
Useful for requests that take longer than average to reply. Hint is provided to clients via ?request-timeout-hint. Note this is only exposed if the device server sets the protocol version to KATCP v5.1 or higher and enables the REQUEST_TIMEOUT_HINTS flag in its PROTOCOL_INFO class attribute
Parameters: timeout_hint : float (seconds) or None
How long the decorated request should reasonably take to reply. No timeout hint if None, similar to never using the decorator, provided for consistency.
Examples
>>> class MyDevice(DeviceServer): ... @return_reply(Int()) ... @request_timeout_hint(15) # Set request timeout hint to 15 seconds ... @tornado.gen.coroutine ... def request_myreq(self, req): ... '''A slow request''' ... result = yield self.slow_operation() ... raise tornado.gen.Return((req, result)) ...
-
katcp.kattypes.
return_reply
(*types, **options)¶ Decorator for returning replies from request handler methods.
The method being decorated should return an iterable of result values. If the first value is ‘ok’, the decorator will check the remaining values against the specified list of types (if any). If the first value is ‘fail’ or ‘error’, there must be only one remaining parameter, and it must be a string describing the failure or error In both cases, the decorator will pack the values into a reply message.
Parameters: types : list of kattypes
The types of the reply message parameters (in order).
Keyword Arguments: major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Examples
>>> class MyDevice(DeviceServer): ... @request(Int()) ... @return_reply(Int(), Float()) ... def request_myreq(self, req, my_int): ... return ("ok", my_int + 1, my_int * 2.0) ...
-
katcp.kattypes.
send_reply
(*types, **options)¶ Decorator for sending replies from request callback methods.
This decorator constructs a reply from a list or tuple returned from a callback method, but unlike the return_reply decorator it also sends the reply rather than returning it.
The list/tuple returned from the callback method must have req (a ClientRequestConnection instance) as its first parameter and the original message as the second. The original message is needed to determine the message name and ID.
The device with the callback method must have a reply method.
Parameters: types : list of kattypes
The types of the reply message parameters (in order).
Keyword Arguments: major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Examples
>>> class MyDevice(DeviceServer): ... @send_reply(Int(), Float()) ... def my_callback(self, req): ... return (req, "ok", 5, 2.0) ...
-
katcp.kattypes.
unpack_message
()¶ Decorator that unpacks katcp.Messages to function arguments.
The method being decorated should take arguments matching the list of types. The decorator will unpack the request message into the arguments.
Parameters: types : list of kattypes
The types of the request message parameters (in order). A type with multiple=True has to be the last type.
Keyword Arguments: include_msg : bool, optional
Pass the request message as the third parameter to the decorated request handler function (default is False).
major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Examples
>>> class MyClient(DeviceClient): ... @unpack_message(Str(), Int(), Float(), Bool()) ... def reply_myreq(self, status, my_int, my_float, my_bool): ... print 'myreq replied with ', (status, my_int, my_float, my_bool) ... ... @unpack_message(Str(), Int(), include_msg=True) ... def inform_fruit_picked(self, msg, fruit, no_picked): ... print no_picked, 'of fruit ', fruit, ' picked.' ... print 'Raw inform message: ', str(msg)
-
katcp.kattypes.
unpack_types
(types, args, argnames, major)¶ Parse arguments according to types list.
Parameters: types : sequence of kattypes
The types of the arguments (in order).
args : sequence of strings
The arguments to parse.
argnames : sequence of strings
The names of the arguments.
major : integer
Major version of KATCP to use when packing types
Returns: unpacked_args : list
List of args after unpacking to kattype objects
-
katcp.kattypes.
unpack_message
() Decorator that unpacks katcp.Messages to function arguments.
The method being decorated should take arguments matching the list of types. The decorator will unpack the request message into the arguments.
Parameters: types : list of kattypes
The types of the request message parameters (in order). A type with multiple=True has to be the last type.
Keyword Arguments: include_msg : bool, optional
Pass the request message as the third parameter to the decorated request handler function (default is False).
major : int, optional
Major version of KATCP to use when interpreting types. Defaults to latest implemented KATCP version.
Examples
>>> class MyClient(DeviceClient): ... @unpack_message(Str(), Int(), Float(), Bool()) ... def reply_myreq(self, status, my_int, my_float, my_bool): ... print 'myreq replied with ', (status, my_int, my_float, my_bool) ... ... @unpack_message(Str(), Int(), include_msg=True) ... def inform_fruit_picked(self, msg, fruit, no_picked): ... print no_picked, 'of fruit ', fruit, ' picked.' ... print 'Raw inform message: ', str(msg)
Low level client API (client)¶
Clients for the KAT device control language.
-
class
katcp.client.
AsyncClient
(host, port, tb_limit=20, timeout=5.0, logger=<logging.Logger object>, auto_reconnect=True)¶ Bases:
katcp.client.DeviceClient
Implement async and callback-based requests on top of DeviceClient.
This client will use message IDs if the server supports them.
Parameters: host : string
Host to connect to.
port : int
Port to connect to.
tb_limit : int, optional
Maximum number of stack frames to send in error traceback.
logger : object, optional
Python Logger object to log to. Default is a logger named ‘katcp’.
auto_reconnect : bool, optional
Whether to automatically reconnect if the connection dies.
timeout : float in seconds, optional
Default number of seconds to wait before a callback callback_request times out. Can be overridden in individual calls to callback_request.
Examples
>>> def reply_cb(msg): ... print "Reply:", msg ... >>> def inform_cb(msg): ... print "Inform:", msg ... >>> c = AsyncClient('localhost', 10000) >>> c.start() >>> c.ioloop.add_callback( ... c.callback_request, ... katcp.Message.request('myreq'), ... reply_cb=reply_cb, ... inform_cb=inform_cb, ... ) ... >>> # expect reply to be printed here >>> # stop the client once we're finished with it >>> c.stop() >>> c.join()
Methods
AsyncClient.blocking_request
(msg[, timeout, …])Send a request message and wait for its reply. AsyncClient.callback_request
(msg[, …])Send a request message. AsyncClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. AsyncClient.disconnect
()Force client connection to close, reconnect if auto-connect set. AsyncClient.enable_thread_safety
()Enable thread-safety features. AsyncClient.future_request
(msg[, timeout, …])Send a request message, with future replies. AsyncClient.handle_inform
(msg)Handle inform messages related to any current requests. AsyncClient.handle_message
(msg)Handle a message from the server. AsyncClient.handle_reply
(msg)Handle a reply message related to the current request. AsyncClient.handle_request
(msg)Dispatch a request message to the appropriate method. AsyncClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. AsyncClient.inform_version
(msg)Handle katcp v4 and below version inform. AsyncClient.inform_version_connect
(msg)Process a #version-connect message. AsyncClient.is_connected
()Check if the socket is currently connected. AsyncClient.join
([timeout])Rejoin the client thread. AsyncClient.next
()AsyncClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. AsyncClient.preset_protocol_flags
(protocol_flags)Preset server protocol flags. AsyncClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. AsyncClient.running
()Whether the client is running. AsyncClient.send_message
(msg)Send any kind of message. AsyncClient.send_request
(msg)Send a request message. AsyncClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. AsyncClient.start
([timeout])Start the client in a new thread. AsyncClient.stop
(*args, **kwargs)Stop a running client. AsyncClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. AsyncClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. AsyncClient.unhandled_request
(msg)Fallback method for requests without a registered handler. AsyncClient.until_connected
(**kwargs)Return future that resolves when the client is connected. AsyncClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. AsyncClient.until_running
([timeout])Return future that resolves when the client is running. AsyncClient.until_stopped
([timeout])Return future that resolves when the client has stopped. AsyncClient.wait_connected
([timeout])Wait until the client is connected. AsyncClient.wait_disconnected
([timeout])Wait until the client is disconnected. AsyncClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. AsyncClient.wait_running
([timeout])Wait until the client is running. -
blocking_request
(msg, timeout=None, use_mid=None)¶ Send a request message and wait for its reply.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
callback_request
(msg, reply_cb=None, inform_cb=None, user_data=None, timeout=None, use_mid=None)¶ Send a request message.
Parameters: msg : Message object
The request message to send.
reply_cb : function
The reply callback with signature reply_cb(msg) or reply_cb(msg, *user_data)
inform_cb : function
The inform callback with signature inform_cb(msg) or inform_cb(msg, *user_data)
user_data : tuple
Optional user data to send to the reply and inform callbacks.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
-
future_request
(msg, timeout=None, use_mid=None)¶ Send a request message, with future replies.
Parameters: msg : Message object
The request Message to send.
timeout : float in seconds
How long to wait for a reply. The default is the the timeout set when creating the AsyncClient.
use_mid : boolean, optional
Whether to use message IDs. Default is to use message IDs if the server supports them.
Returns: A tornado.concurrent.Future that resolves with: :
reply : Message object
The reply message received.
informs : list of Message objects
A list of the inform messages received.
-
handle_inform
(msg)¶ Handle inform messages related to any current requests.
Inform messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The inform message to dispatch.
-
handle_reply
(msg)¶ Handle a reply message related to the current request.
Reply messages not related to the current request go up to the base class method.
Parameters: msg : Message object
The reply message to dispatch.
-
stop
(*args, **kwargs)¶ Stop a running client.
If using a managed ioloop, this must be called from a different thread to the ioloop’s. This method only returns once the client’s main coroutine, _install(), has completed.
If using an unmanaged ioloop, this can be called from the same thread as the ioloop. The until_stopped() method can be used to wait on completion of the main coroutine, _install().
Parameters: timeout : float in seconds
Seconds to wait for both client thread to have started, and for stopping.
-
-
class
katcp.client.
BlockingClient
(host, port, tb_limit=20, timeout=5.0, logger=<logging.Logger object>, auto_reconnect=True)¶ Bases:
katcp.client.CallbackClient
Methods
BlockingClient.blocking_request
(msg[, …])Send a request message and wait for its reply. BlockingClient.callback_request
(msg[, …])Send a request message. BlockingClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. BlockingClient.disconnect
()Force client connection to close, reconnect if auto-connect set. BlockingClient.enable_thread_safety
()Enable thread-safety features. BlockingClient.future_request
(msg[, …])Send a request message, with future replies. BlockingClient.handle_inform
(msg)Handle inform messages related to any current requests. BlockingClient.handle_message
(msg)Handle a message from the server. BlockingClient.handle_reply
(msg)Handle a reply message related to the current request. BlockingClient.handle_request
(msg)Dispatch a request message to the appropriate method. BlockingClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. BlockingClient.inform_version
(msg)Handle katcp v4 and below version inform. BlockingClient.inform_version_connect
(msg)Process a #version-connect message. BlockingClient.is_connected
()Check if the socket is currently connected. BlockingClient.join
([timeout])Rejoin the client thread. BlockingClient.next
()BlockingClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. BlockingClient.preset_protocol_flags
(…)Preset server protocol flags. BlockingClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. BlockingClient.running
()Whether the client is running. BlockingClient.send_message
(msg)Send any kind of message. BlockingClient.send_request
(msg)Send a request message. BlockingClient.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False BlockingClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. BlockingClient.start
([timeout])Start the client in a new thread. BlockingClient.stop
(*args, **kwargs)Stop a running client. BlockingClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. BlockingClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. BlockingClient.unhandled_request
(msg)Fallback method for requests without a registered handler. BlockingClient.until_connected
(**kwargs)Return future that resolves when the client is connected. BlockingClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. BlockingClient.until_running
([timeout])Return future that resolves when the client is running. BlockingClient.until_stopped
([timeout])Return future that resolves when the client has stopped. BlockingClient.wait_connected
([timeout])Wait until the client is connected. BlockingClient.wait_disconnected
([timeout])Wait until the client is disconnected. BlockingClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. BlockingClient.wait_running
([timeout])Wait until the client is running.
-
class
katcp.client.
CallbackClient
(host, port, tb_limit=20, timeout=5.0, logger=<logging.Logger object>, auto_reconnect=True)¶ Bases:
katcp.client.AsyncClient
Methods
CallbackClient.blocking_request
(msg[, …])Send a request message and wait for its reply. CallbackClient.callback_request
(msg[, …])Send a request message. CallbackClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. CallbackClient.disconnect
()Force client connection to close, reconnect if auto-connect set. CallbackClient.enable_thread_safety
()Enable thread-safety features. CallbackClient.future_request
(msg[, …])Send a request message, with future replies. CallbackClient.handle_inform
(msg)Handle inform messages related to any current requests. CallbackClient.handle_message
(msg)Handle a message from the server. CallbackClient.handle_reply
(msg)Handle a reply message related to the current request. CallbackClient.handle_request
(msg)Dispatch a request message to the appropriate method. CallbackClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. CallbackClient.inform_version
(msg)Handle katcp v4 and below version inform. CallbackClient.inform_version_connect
(msg)Process a #version-connect message. CallbackClient.is_connected
()Check if the socket is currently connected. CallbackClient.join
([timeout])Rejoin the client thread. CallbackClient.next
()CallbackClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. CallbackClient.preset_protocol_flags
(…)Preset server protocol flags. CallbackClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. CallbackClient.running
()Whether the client is running. CallbackClient.send_message
(msg)Send any kind of message. CallbackClient.send_request
(msg)Send a request message. CallbackClient.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False CallbackClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. CallbackClient.start
([timeout])Start the client in a new thread. CallbackClient.stop
(*args, **kwargs)Stop a running client. CallbackClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. CallbackClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. CallbackClient.unhandled_request
(msg)Fallback method for requests without a registered handler. CallbackClient.until_connected
(**kwargs)Return future that resolves when the client is connected. CallbackClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. CallbackClient.until_running
([timeout])Return future that resolves when the client is running. CallbackClient.until_stopped
([timeout])Return future that resolves when the client has stopped. CallbackClient.wait_connected
([timeout])Wait until the client is connected. CallbackClient.wait_disconnected
([timeout])Wait until the client is disconnected. CallbackClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. CallbackClient.wait_running
([timeout])Wait until the client is running. -
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
-
class
katcp.client.
DeviceClient
(host, port, tb_limit=20, logger=<logging.Logger object>, auto_reconnect=True)¶ Bases:
future.types.newobject.newobject
Device client proxy.
Subclasses should implement .reply_*, .inform_* and send_request_* methods to take actions when messages arrive, and implement unhandled_inform, unhandled_reply and unhandled_request to provide fallbacks for messages for which there is no handler.
Request messages can be sent by calling .send_request().
Parameters: host : string
Host to connect to.
port : int
Port to connect to.
tb_limit : int
Maximum number of stack frames to send in error traceback.
logger : object
Python Logger object to log to.
auto_reconnect : bool
Whether to automatically reconnect if the connection dies.
Notes
The client may block its ioloop if the default blocking tornado DNS resolver is used. When an ioloop is shared, it would make sense to configure one of the non-blocking resolver classes, see http://tornado.readthedocs.org/en/latest/netutil.html
Examples
>>> MyClient(DeviceClient): ... def reply_myreq(self, msg): ... print str(msg) ... >>> c = MyClient('localhost', 10000) >>> c.start() >>> c.send_request(katcp.Message.request('myreq')) >>> # expect reply to be printed here >>> # stop the client once we're finished with it >>> c.stop() >>> c.join()
Methods
DeviceClient.convert_seconds
(time_seconds)Convert a time in seconds to the device timestamp units. DeviceClient.disconnect
()Force client connection to close, reconnect if auto-connect set. DeviceClient.enable_thread_safety
()Enable thread-safety features. DeviceClient.handle_inform
(msg)Dispatch an inform message to the appropriate method. DeviceClient.handle_message
(msg)Handle a message from the server. DeviceClient.handle_reply
(msg)Dispatch a reply message to the appropriate method. DeviceClient.handle_request
(msg)Dispatch a request message to the appropriate method. DeviceClient.inform_build_state
(msg)Handle katcp v4 and below build-state inform. DeviceClient.inform_version
(msg)Handle katcp v4 and below version inform. DeviceClient.inform_version_connect
(msg)Process a #version-connect message. DeviceClient.is_connected
()Check if the socket is currently connected. DeviceClient.join
([timeout])Rejoin the client thread. DeviceClient.next
()DeviceClient.notify_connected
(connected)Event handler that is called whenever the connection status changes. DeviceClient.preset_protocol_flags
(…)Preset server protocol flags. DeviceClient.request
(msg[, use_mid])Send a request message, with automatic message ID assignment. DeviceClient.running
()Whether the client is running. DeviceClient.send_message
(msg)Send any kind of message. DeviceClient.send_request
(msg)Send a request message. DeviceClient.set_ioloop
([ioloop])Set the tornado.ioloop.IOLoop instance to use. DeviceClient.start
([timeout])Start the client in a new thread. DeviceClient.stop
([timeout])Stop a running client. DeviceClient.unhandled_inform
(msg)Fallback method for inform messages without a registered handler. DeviceClient.unhandled_reply
(msg)Fallback method for reply messages without a registered handler. DeviceClient.unhandled_request
(msg)Fallback method for requests without a registered handler. DeviceClient.until_connected
(**kwargs)Return future that resolves when the client is connected. DeviceClient.until_protocol
(**kwargs)Return future that resolves after receipt of katcp protocol info. DeviceClient.until_running
([timeout])Return future that resolves when the client is running. DeviceClient.until_stopped
([timeout])Return future that resolves when the client has stopped. DeviceClient.wait_connected
([timeout])Wait until the client is connected. DeviceClient.wait_disconnected
([timeout])Wait until the client is disconnected. DeviceClient.wait_protocol
([timeout])Wait until katcp protocol information has been received from server. DeviceClient.wait_running
([timeout])Wait until the client is running. -
MAX_LOOP_LATENCY
= 0.03¶ Do not spend more than this many seconds reading pipelined socket data
IOStream inline-reading can result in ioloop starvation (see https://groups.google.com/forum/#!topic/python-tornado/yJrDAwDR_kA).
-
MAX_MSG_SIZE
= 2097152¶ Maximum message size that can be received in bytes.
If more than MAX_MSG_SIZE bytes are read from the socket without encountering a message terminator (i.e. newline), the connection is closed.
-
MAX_WRITE_BUFFER_SIZE
= 4194304¶ Maximum outstanding bytes to be buffered by the server process.
If more than MAX_WRITE_BUFFER_SIZE bytes are outstanding, the connection is closed. Note that the OS also buffers socket writes, so more than MAX_WRITE_BUFFER_SIZE bytes may be untransmitted in total.
-
bind_address
¶ (host, port) where the client is connecting
-
convert_seconds
(time_seconds)¶ Convert a time in seconds to the device timestamp units.
KATCP v4 and earlier, specified all timestamps in milliseconds. Since KATCP v5, all timestamps are in seconds. If the device KATCP version has been detected, this method converts a value in seconds to the appropriate (seconds or milliseconds) quantity. For version smaller than V4, the time value will be truncated to the nearest millisecond.
-
disconnect
()¶ Force client connection to close, reconnect if auto-connect set.
-
enable_thread_safety
()¶ Enable thread-safety features.
Must be called before start().
-
handle_inform
(msg)¶ Dispatch an inform message to the appropriate method.
Parameters: msg : Message object
The inform message to dispatch.
-
handle_message
(msg)¶ Handle a message from the server.
Parameters: msg : Message object
The Message to dispatch to the handler methods.
-
handle_reply
(msg)¶ Dispatch a reply message to the appropriate method.
Parameters: msg : Message object
The reply message to dispatch.
-
handle_request
(msg)¶ Dispatch a request message to the appropriate method.
Parameters: msg : Message object
The request message to dispatch.
-
inform_build_state
(msg)¶ Handle katcp v4 and below build-state inform.
-
inform_version
(msg)¶ Handle katcp v4 and below version inform.
-
inform_version_connect
(msg)¶ Process a #version-connect message.
-
is_connected
()¶ Check if the socket is currently connected.
Returns: connected : bool
Whether the client is connected.
-
join
(timeout=None)¶ Rejoin the client thread.
Parameters: timeout : float in seconds
Seconds to wait for thread to finish.
Notes
Does nothing if the ioloop is not managed. Use until_stopped() instead.
-
notify_connected
(connected)¶ Event handler that is called whenever the connection status changes.
Override in derived class for desired behaviour.
Note
This function should never block. Doing so will cause the client to cease processing data from the server until notify_connected completes.
Parameters: connected : bool
Whether the client has just connected (True) or just disconnected (False).
-
preset_protocol_flags
(protocol_flags)¶ Preset server protocol flags.
Sets the assumed server protocol flags and disables automatic server version detection.
Parameters: protocol_flags : katcp.core.ProtocolFlags instance
-
request
(msg, use_mid=None)¶ Send a request message, with automatic message ID assignment.
Parameters: msg : katcp.Message request message
use_mid : bool or None, default=None
Returns: mid : string or None
The message id, or None if no msg id is used
If use_mid is None and the server supports msg ids, or if use_mid is :
True a message ID will automatically be assigned msg.mid is None. :
if msg.mid has a value, and the server supports msg ids, that value :
will be used. If the server does not support msg ids, KatcpVersionError :
will be raised. :
-
running
()¶ Whether the client is running.
Returns: running : bool
Whether the client is running.
-
send_message
(msg)¶ Send any kind of message.
Parameters: msg : Message object
The message to send.
-
send_request
(msg)¶ Send a request message.
Parameters: msg : Message object
The request Message to send.
-
set_ioloop
(ioloop=None)¶ Set the tornado.ioloop.IOLoop instance to use.
This defaults to IOLoop.current(). If set_ioloop() is never called the IOLoop is managed: started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called
-
start
(timeout=None)¶ Start the client in a new thread.
Parameters: timeout : float in seconds
Seconds to wait for client thread to start. Do not specify a timeout if start() is being called from the same ioloop that this client will be installed on, since it will block the ioloop without progressing.
-
stop
(timeout=None)¶ Stop a running client.
If using a managed ioloop, this must be called from a different thread to the ioloop’s. This method only returns once the client’s main coroutine, _install(), has completed.
If using an unmanaged ioloop, this can be called from the same thread as the ioloop. The until_stopped() method can be used to wait on completion of the main coroutine, _install().
Parameters: timeout : float in seconds
Seconds to wait for both client thread to have started, and for stopping.
-
unhandled_inform
(msg)¶ Fallback method for inform messages without a registered handler.
Parameters: msg : Message object
The inform message that wasn’t processed by any handlers.
-
unhandled_reply
(msg)¶ Fallback method for reply messages without a registered handler.
Parameters: msg : Message object
The reply message that wasn’t processed by any handlers.
-
unhandled_request
(msg)¶ Fallback method for requests without a registered handler.
Parameters: msg : Message object
The request message that wasn’t processed by any handlers.
-
until_connected
(**kwargs)¶ Return future that resolves when the client is connected.
-
until_protocol
(**kwargs)¶ Return future that resolves after receipt of katcp protocol info.
If the returned future resolves, the server’s protocol information is available in the ProtocolFlags instance self.protocol_flags.
-
until_running
(timeout=None)¶ Return future that resolves when the client is running.
Notes
Must be called from the same ioloop as the client.
-
until_stopped
(timeout=None)¶ Return future that resolves when the client has stopped.
Parameters: timeout : float in seconds
Seconds to wait for the client to stop.
Notes
If already running, stop() must be called before this.
Must be called from the same ioloop as the client. If using a different thread, or a managed ioloop, this method should not be used. Use join() instead.
Also note that stopped != not running. Stopped means the main coroutine has ended, or was never started. When stopping, the running flag is cleared some time before stopped is set.
-
wait_connected
(timeout=None)¶ Wait until the client is connected.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: connected : bool
Whether the client is connected.
Notes
Do not call this from the ioloop, use until_connected().
-
wait_disconnected
(timeout=None)¶ Wait until the client is disconnected.
Parameters: timeout : float in seconds
Seconds to wait for the client to disconnect.
Returns: disconnected : bool
Whether the client is disconnected.
Notes
Do not call this from the ioloop, use until_disconnected().
-
wait_protocol
(timeout=None)¶ Wait until katcp protocol information has been received from server.
Parameters: timeout : float in seconds
Seconds to wait for the client to connect.
Returns: received : bool
Whether protocol information was received
If this method returns True, the server’s protocol information is :
available in the ProtocolFlags instance self.protocol_flags. :
Notes
Do not call this from the ioloop, use until_protocol().
-
wait_running
(timeout=None)¶ Wait until the client is running.
Parameters: timeout : float in seconds
Seconds to wait for the client to start running.
Returns: running : bool
Whether the client is running
Notes
Do not call this from the ioloop, use until_running().
-
-
katcp.client.
make_threadsafe
(meth)¶ Decorator for a DeviceClient method that should always run in ioloop.
Used with DeviceClient.enable_thread_safety(). If not called the method will be unprotected and it is the user’s responsibility to ensure that these methods are only called from the ioloop, otherwise the decorated methods are wrapped. Should only be used for functions that have no return value.
-
katcp.client.
make_threadsafe_blocking
(meth)¶ Decorator for a DeviceClient method that will block.
Used with DeviceClient.enable_thread_safety(). Used to provide blocking calls that can be made from other threads. If called in ioloop context, calls the original method directly to prevent deadlocks. Will route return value to caller. Add timeout keyword argument to limit blocking time. If meth returns a future, its result will be returned, otherwise its result will be passed back directly.
-
katcp.client.
request_check
(client, exception, *msg_parms, **kwargs)¶ Make blocking request to client and raise exception if reply is not ok.
Parameters: client : DeviceClient instance
exception: Exception class to raise :
*msg_parms : Message parameters sent to the Message.request() call
**kwargs : Keyword arguments
Forwards kwargs[‘timeout’] to client.blocking_request(). Forwards kwargs[‘mid’] to Message.request().
Returns: reply, informs : as returned by client.blocking_request
Raises: *exception* passed as parameter is raised if reply.reply_ok() is False :
Notes
A typical use-case for this function is to use functools.partial() to bind a particular client and exception. The resulting function can then be used instead of direct client.blocking_request() calls to automate error handling.
Concrete Intermediate-level KATCP Client API (inspecting_client)¶
-
class
katcp.inspecting_client.
ExponentialRandomBackoff
(delay_initial=1.0, delay_max=90.0, exp_fac=3.0, randomicity=0.95)¶ Bases:
future.types.newobject.newobject
Methods
ExponentialRandomBackoff.failed
()Call whenever an action has failed, grows delay exponentially ExponentialRandomBackoff.next
()ExponentialRandomBackoff.success
()Call whenever an action has succeeded, resets delay to minimum -
exp_fac
= None¶ Increase timeout by this factor for each consecutive failure
-
failed
()¶ Call whenever an action has failed, grows delay exponentially
After calling failed(), the delay property contains the next delay
-
success
()¶ Call whenever an action has succeeded, resets delay to minimum
-
-
class
katcp.inspecting_client.
InspectingClientAsync
(host, port, ioloop=None, initial_inspection=None, auto_reconnect=True, logger=<logging.Logger object>)¶ Bases:
future.types.newobject.newobject
Higher-level client that inspects a KATCP interface.
Note: This class is not thread-safe at present, it should only be called from the ioloop.
Note: always call stop() after start() and you are done with the container to make sure the container cleans up correctly.
Methods
InspectingClientAsync.close
()InspectingClientAsync.connect
(**kwargs)Connect to KATCP interface, starting what is needed InspectingClientAsync.future_check_request
(…)Check if the request exists. InspectingClientAsync.future_check_sensor
(…)Check if the sensor exists. InspectingClientAsync.future_get_request
(…)Get the request object. InspectingClientAsync.future_get_sensor
(**kwargs)Get the sensor object. InspectingClientAsync.handle_sensor_value
()Handle #sensor-value informs just like #sensor-status informs InspectingClientAsync.inform_hook_client_factory
(…)Return an instance of _InformHookDeviceClient
or similarInspectingClientAsync.inspect
(**kwargs)Inspect device requests and sensors, update model. InspectingClientAsync.inspect_requests
(**kwargs)Inspect all or one requests on the device. InspectingClientAsync.inspect_sensors
(**kwargs)Inspect all or one sensor on the device. InspectingClientAsync.is_connected
()Connection status. InspectingClientAsync.join
([timeout])InspectingClientAsync.next
()InspectingClientAsync.preset_protocol_flags
(…)Preset server protocol flags. InspectingClientAsync.request_factory
Factory that produces KATCP Request objects. InspectingClientAsync.sensor_factory
alias of katcp.core.Sensor
InspectingClientAsync.set_ioloop
(ioloop)InspectingClientAsync.set_state_callback
(cb)Set user callback for state changes InspectingClientAsync.simple_request
(…)Create and send a request to the server. InspectingClientAsync.start
([timeout])Note: always call stop() and wait until_stopped() when you are done with the container to make sure the container cleans up correctly. InspectingClientAsync.stop
([timeout])InspectingClientAsync.until_connected
([timeout])InspectingClientAsync.until_data_synced
([…])InspectingClientAsync.until_not_synced
([timeout])InspectingClientAsync.until_state
(desired_state)Wait until state is desired_state, InspectingClientStateType instance InspectingClientAsync.until_stopped
([timeout])Return future that resolves when the client has stopped InspectingClientAsync.until_synced
([timeout])InspectingClientAsync.update_sensor
(**kwargs)-
connect
(**kwargs)¶ Connect to KATCP interface, starting what is needed
Parameters: timeout : float, None
Time to wait until connected. No waiting if None.
Raises: :class:`tornado.gen.TimeoutError` if the connect timeout expires :
-
connected
¶ Connection status.
-
future_check_request
(**kwargs)¶ Check if the request exists.
Used internally by future_get_request. This method is aware of synchronisation in progress and if inspection of the server is allowed.
Parameters: name : str
Name of the request to verify.
update : bool or None, optional
If a katcp request to the server should be made to check if the sensor is on the server. True = Allow, False do not Allow, None use the class default.
Notes
Ensure that self.state.data_synced == True if yielding to future_check_request from a state-change callback, or a deadlock will occur.
-
future_check_sensor
(**kwargs)¶ Check if the sensor exists.
Used internally by future_get_sensor. This method is aware of synchronisation in progress and if inspection of the server is allowed.
Parameters: name : str
Name of the sensor to verify.
update : bool or None, optional
If a katcp request to the server should be made to check if the sensor is on the server now.
Notes
Ensure that self.state.data_synced == True if yielding to future_check_sensor from a state-change callback, or a deadlock will occur.
-
future_get_request
(**kwargs)¶ Get the request object.
Check if we have information for this request, if not connect to server and update (if allowed).
Parameters: name : string
Name of the request.
update : bool or None, optional
True allow inspect client to inspect katcp server if the request is not known.
Returns: Request created by :meth:`request_factory` or None if request not found. :
Notes
Ensure that self.state.data_synced == True if yielding to future_get_request from a state-change callback, or a deadlock will occur.
-
future_get_sensor
(**kwargs)¶ Get the sensor object.
Check if we have information for this sensor, if not connect to server and update (if allowed) to get information.
Parameters: name : string
Name of the sensor.
update : bool or None, optional
True allow inspect client to inspect katcp server if the sensor is not known.
Returns: Sensor created by :meth:`sensor_factory` or None if sensor not found. :
Notes
Ensure that self.state.data_synced == True if yielding to future_get_sensor from a state-change callback, or a deadlock will occur.
-
handle_sensor_value
()¶ Handle #sensor-value informs just like #sensor-status informs
-
inform_hook_client_factory
(host, port, *args, **kwargs)¶ Return an instance of
_InformHookDeviceClient
or similarProvided to ease testing. Dynamically overriding this method after instantiation but before start() is called allows for deep brain surgery. See
katcp.fake_clients.TBD
-
inspect
(**kwargs)¶ Inspect device requests and sensors, update model.
Returns: Tornado future that resolves with: :
model_changes : Nested AttrDict or None
Contains sets of added/removed request/sensor names
Example structure:
{ 'requests':{ 'added': set(['req1', 'req2']), 'removed': set(['req10', 'req20']) } 'sensors': { 'added': set(['sens1', 'sens2']), 'removed': set(['sens10', 'sens20']) } }
If there are no changes keys may be omitted. If an item is in both the ‘added’ and ‘removed’ sets that means that it changed.
If neither request not sensor changes are present, None is returned instead of a nested structure.
-
inspect_requests
(**kwargs)¶ Inspect all or one requests on the device. Update requests index.
Parameters: name : str or None, optional
Name of the request or None to get all requests.
timeout : float or None, optional
Timeout for request inspection, None for no timeout
Returns: Tornado future that resolves with: :
changes :
AttrDict
AttrDict with keys
added
andremoved
(of typeset
), listing the requests that have been added or removed respectively. Modified requests are listed in both. If there are no changes, returnsNone
instead.Example structure:
{ 'added': set(['req1', 'req2']), 'removed': set(['req10', 'req20']) }
-
inspect_sensors
(**kwargs)¶ Inspect all or one sensor on the device. Update sensors index.
Parameters: name : str or None, optional
Name of the sensor or None to get all sensors.
timeout : float or None, optional
Timeout for sensors inspection, None for no timeout
Returns: Tornado future that resolves with: :
changes :
AttrDict
AttrDict with keys
added
andremoved
(of typeset
), listing the sensors that have been added or removed respectively. Modified sensors are listed in both. If there are no changes, returnsNone
instead.Example structure:
{ 'added': set(['sens1', 'sens2']), 'removed': set(['sens10', 'sens20']) }
-
is_connected
()¶ Connection status.
-
preset_protocol_flags
(protocol_flags)¶ Preset server protocol flags.
Sets the assumed server protocol flags and disables automatic server version detection.
Parameters: protocol_flags : katcp.core.ProtocolFlags instance
-
request_factory
¶ Factory that produces KATCP Request objects.
signature: request_factory(name, description, timeout_hint), all parameters passed as kwargs
Should be set before calling connect()/start().
Methods
Request.count
Request.index
alias of
Request
-
requests
¶ A list of possible requests.
-
resync_delay
= None¶ Set to an ExponentialRandomBackoff instance in _state_loop
-
sensor_factory
¶ alias of
katcp.core.Sensor
-
sensors
¶ A list of known sensors.
-
set_state_callback
(cb)¶ Set user callback for state changes
Called as
cb(state, model_changes)
where state is an
InspectingClientStateType
instance, and model_changes is anAttrDict
. The latter may contain keysrequests
andsensors
to describe changes to requests or sensors respectively. These in turn have attributesadded
andremoved
which are sets of request/sensor names. Requests/sensors that have been modified will appear in both sets.Warning
It is possible for model_changes to be
None
, or for eitherrequests
orsensors
to be absent from model_changes.
-
simple_request
(request, *args, **kwargs)¶ Create and send a request to the server.
This method implements a very small subset of the options possible to send an request. It is provided as a shortcut to sending a simple request.
Parameters: request : str
The request to call.
*args : list of objects
Arguments to pass on to the request.
Keyword Arguments: timeout : float or None, optional
Timeout after this amount of seconds (keyword argument).
mid : None or int, optional
Message identifier to use for the request message. If None, use either auto-incrementing value or no mid depending on the KATCP protocol version (mid’s were only introduced with KATCP v5) and the value of the use_mid argument. Defaults to None
use_mid : bool
Use a mid for the request if True. Defaults to True if the server supports them.
Returns: future object. :
Examples
reply, informs = yield ic.simple_request('help', 'sensor-list')
-
start
(timeout=None)¶ Note: always call stop() and wait until_stopped() when you are done with the container to make sure the container cleans up correctly.
-
state
¶ Current client state.
-
synced
¶ Boolean indicating if the device has been synchronised.
-
until_state
(desired_state, timeout=None)¶ Wait until state is desired_state, InspectingClientStateType instance
Returns a future
-
until_stopped
(timeout=None)¶ Return future that resolves when the client has stopped
See the DeviceClient.until_stopped docstring for parameter definitions and more info.
-
-
class
katcp.inspecting_client.
InspectingClientStateType
¶ Bases:
katcp.inspecting_client.InspectingClientStateType
States tuple for the inspecting client. Fields, all bool:
- connected: bool
- TCP connection has been established with the server.
- synced: bool
- The inspecting client and the user that interfaces through the state change callback are all synchronised with the current device state. Also implies connected = True and data_synced = True.
- model_changed: bool
- The device has changed in some way, resulting in the device model being out of date.
- data_synced: bool
- The inspecting client’s internal representation of the device is up to date, although state change user is not yet up to date.
Methods
InspectingClientStateType.count
(value)InspectingClientStateType.index
(value, …)Raises ValueError if the value is not present.
-
katcp.inspecting_client.
RequestType
¶ alias of
katcp.inspecting_client.Request
-
exception
katcp.inspecting_client.
SyncError
¶ Bases:
exceptions.Exception
Raised if an error occurs during syncing with a device
Abstract High-level KATCP Client API (resource)¶
A high-level abstract interface to KATCP clients, sensors and requests.
-
class
katcp.resource.
KATCPDummyRequest
(request_description, is_active=<function <lambda>>)¶ Bases:
katcp.resource.KATCPRequest
Dummy counterpart to KATCPRequest that always returns a successful reply
Methods
KATCPDummyRequest.is_active
()True if resource for this request is active KATCPDummyRequest.issue_request
(*args, **kwargs)Signature as for __call__ KATCPDummyRequest.next
()-
issue_request
(*args, **kwargs)¶ Signature as for __call__
Do the request immediately without checking active state.
-
-
class
katcp.resource.
KATCPReply
¶ Bases:
katcp.resource._KATCPReplyTuple
Container for return messages of KATCP request (reply and informs).
This is based on a named tuple with ‘reply’ and ‘informs’ fields so that the
KATCPReply
object can still be unpacked into a normal tuple.Parameters: reply :
katcp.Message
objectReply message returned by katcp request
informs : list of
katcp.Message
objectsList of inform messages returned by KATCP request
Attributes
messages: list of katcp.Message
objectsList of all messages returned by KATCP request, reply first reply: katcp.Message
objectReply message returned by KATCP request informs: list of katcp.Message
objectsList of inform messages returned by KATCP request The instance evaluates to nonzero (i.e. truthy) if the request succeeded. Methods
KATCPReply.count
(value)KATCPReply.index
(value, [start, [stop]])Raises ValueError if the value is not present. -
messages
¶ List of all messages returned by KATCP request, reply first.
-
succeeded
¶ True if request succeeded (i.e. first reply argument is ‘ok’).
-
-
class
katcp.resource.
KATCPRequest
(request_description, is_active=<function <lambda>>)¶ Bases:
future.types.newobject.newobject
Abstract Base class to serve as the definition of the KATCPRequest API.
Wrapper around a specific KATCP request to a given KATCP device. Each available KATCP request for a particular device has an associated
KATCPRequest
object in the object hierarchy. This wrapper is mainly for interactive convenience. It provides the KATCP request help string as a docstring and pretty-prints the result of the request.Methods
KATCPRequest.is_active
()True if resource for this request is active KATCPRequest.issue_request
(*args, **kwargs)Signature as for __call__ KATCPRequest.next
()-
description
¶ Description of KATCP request as obtained from the ?help request.
-
is_active
()¶ True if resource for this request is active
-
issue_request
(*args, **kwargs)¶ Signature as for __call__
Do the request immediately without checking active state.
-
name
¶ Name of the KATCP request.
-
timeout_hint
¶ Request timeout suggested by device or None if not provided
-
-
class
katcp.resource.
KATCPResource
¶ Bases:
future.types.newobject.newobject
Base class to serve as the definition of the KATCPResource API.
A class C implementing the KATCPResource API should register itself using KATCPResource.register(C) or subclass KATCPResource directly. A complication involved with subclassing is that all the abstract properties must be implemented as properties; normal instance attributes cannot be used.
Attributes
Apart from the abstract properties described below TODO Describe how hierarchies are implemented. Also all other descriptions here so that the sphinx doc can be auto-generated from here. Methods
KATCPResource.is_active
()KATCPResource.list_sensors
([filter, …])List sensors available on this resource matching certain criteria. KATCPResource.next
()KATCPResource.set_active
(active)KATCPResource.set_sampling_strategies
(**kwargs)Set a sampling strategy for all sensors that match the specified filter. KATCPResource.set_sampling_strategy
(**kwargs)Set a sampling strategy for a specific sensor. KATCPResource.wait
(**kwargs)Wait for a sensor in this resource to satisfy a condition. -
address
¶ Address of the underlying client/device.
Type: tuple(host, port) or None, with host a string and port an integer.
If this KATCPResource is not associated with a specific KATCP device (e.g. it is only a top-level container for a hierarchy of KATCP resources), the address should be None.
-
children
¶ AttrDict of subordinate KATCPResource objects keyed by their names.
-
description
¶ Description of this KATCP resource.
-
is_connected
¶ Indicate whether the underlying client/device is connected or not.
-
list_sensors
(filter='', strategy=False, status='', use_python_identifiers=True, tuple=False, refresh=False)¶ List sensors available on this resource matching certain criteria.
Parameters: filter : string, optional
Filter each returned sensor’s name against this regexp if specified. To ease the dichotomy between Python identifier names and actual sensor names, the default is to search on Python identifier names rather than KATCP sensor names, unless use_python_identifiers below is set to False. Note that the sensors of subordinate KATCPResource instances may have inconsistent names and Python identifiers, better to always search on Python identifiers in this case.
strategy : {False, True}, optional
Only list sensors with a set strategy if True
status : string, optional
Filter each returned sensor’s status against this regexp if given
use_python_identifiers : {True, False}, optional
Match on python identifiers even the the KATCP name is available.
tuple : {True, False}, optional, Default: False
Return backwards compatible tuple instead of SensorResultTuples
refresh : {True, False}, optional, Default: False
If set the sensor values will be refreshed with get_value before returning the results.
Returns: sensors : list of SensorResultTuples, or list of tuples
List of matching sensors presented as named tuples. The object field is the
KATCPSensor
object associated with the sensor. Note that the name of the object may not match name if it originates from a subordinate device.
-
name
¶ Name of this KATCP resource.
-
parent
¶ Parent KATCPResource object of this subordinate resource, or None.
-
req
¶ Attribute root/container for all KATCP request wrappers.
Each KATCP request that is exposed on a KATCP device should have a corresponding
KATCPRequest
object so that callingresource.req.request_name(arg1, arg2, …)sends a ‘?request-name arg1 arg2 …’ message to the KATCP device and waits for the associated inform-reply and reply messages.
For a
KATCPResource
object that exposes a hierarchical device it can choose to include lower-level request handlers here such that resource.req.dev_request() maps to resource.dev.req.request().
-
sensor
¶ Attribute root/container for all KATCP sensor wrappers.
Each KATCP sensor that is exposed on a KATCP device should have a corresponding
KATCPSensor
object so thatresource.sensor.sensor_namecorresponds to a sensor named e.g. ‘sensor-name’, where the object or attribute name is an escaped/Pythonised version of the original sensor name (see
escape_name()
for the escape mechanism). Hopefully the device is not crazy enough to have multiple sensors that map to the same Python identifier.A
KATCPResource
object that exposes a hierarchical device can choose to include lower-level sensors here such that resource.sensor.dev_sensorname maps to resource.dev.sensor.sensorname.
-
set_sampling_strategies
(**kwargs)¶ Set a sampling strategy for all sensors that match the specified filter.
Parameters: filter : string
The regular expression filter to use to select the sensors to which to apply the specified strategy. Use “” to match all sensors. Is matched using
list_sensors()
.strategy_and_params : seq of str or str
As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
**list_sensor_args : keyword arguments
Passed to the
list_sensors()
call as kwargsReturns: sensors_strategies : tornado Future
resolves with a dict with the Python identifier names of the sensors as keys and the value a tuple:
(success, info) with
- success : bool
True if setting succeeded for this sensor, else False
- info : tuple
normalised sensor strategy and parameters as tuple if success == True else, sys.exc_info() tuple for the error that occurred.
-
set_sampling_strategy
(**kwargs)¶ Set a sampling strategy for a specific sensor.
Parameters: sensor_name : string
The specific sensor.
strategy_and_params : seq of str or str
As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: sensors_strategies : tornado Future
resolves with a dict with the Python identifier names of the sensors as keys and the value a tuple:
(success, info) with
- success : bool
True if setting succeeded for this sensor, else False
- info : tuple
normalised sensor strategy and parameters as tuple if success == True else, sys.exc_info() tuple for the error that occurred.
-
wait
(**kwargs)¶ Wait for a sensor in this resource to satisfy a condition.
Parameters: sensor_name : string
The name of the sensor to check
condition_or_value : obj or callable, or seq of objs or callables
If obj, sensor.value is compared with obj. If callable, condition_or_value(reading) is called, and must return True if its condition is satisfied. Since the reading is passed in, the value, status, timestamp or received_timestamp attributes can all be used in the check.
timeout : float or None
The timeout in seconds (None means wait forever)
Returns: This command returns a tornado Future that resolves with True when the :
sensor value satisfies the condition, or False if the condition is :
still not satisfied after a given timeout period. :
Raises: :class:`KATCPSensorError` :
If the sensor does not have a strategy set, or if the named sensor is not present
-
-
exception
katcp.resource.
KATCPResourceError
¶ Bases:
exceptions.Exception
Error raised for resource-related errors
-
exception
katcp.resource.
KATCPResourceInactive
¶ Bases:
katcp.resource.KATCPResourceError
Raised when a request is made to an inactive resource
-
class
katcp.resource.
KATCPSensor
(sensor_description, sensor_manager)¶ Bases:
future.types.newobject.newobject
Wrapper around a specific KATCP sensor on a given KATCP device.
Each available KATCP sensor for a particular device has an associated
KATCPSensor
object in the object hierarchy. This wrapper is mainly for interactive convenience. It provides the KATCP request help string as a docstring and registers listeners. Subclasses need to call the base class version of __init__().Methods
KATCPSensor.call_listeners
(reading)KATCPSensor.clear_listeners
()Clear any registered listeners to updates from this sensor. KATCPSensor.drop_sampling_strategy
()Drop memorised sampling strategy for sensor, if any KATCPSensor.get_reading
(**kwargs)Get a fresh sensor reading from the KATCP resource KATCPSensor.get_status
(**kwargs)Get a fresh sensor status from the KATCP resource KATCPSensor.get_value
(**kwargs)Get a fresh sensor value from the KATCP resource KATCPSensor.is_listener
(listener)KATCPSensor.next
()KATCPSensor.parse_value
(s_value)Parse a value from a string. KATCPSensor.register_listener
(listener[, …])Add a callback function that is called when sensor value is updated. KATCPSensor.set
(timestamp, status, value)Set sensor with a given received value, matches katcp.Sensor.set()
KATCPSensor.set_formatted
(raw_timestamp, …)Set sensor using KATCP string formatted inputs KATCPSensor.set_sampling_strategy
(strategy)Set current sampling strategy for sensor KATCPSensor.set_strategy
(strategy[, params])Set current sampling strategy for sensor. KATCPSensor.set_value
(value[, status, timestamp])Set sensor value with optinal specification of status and timestamp KATCPSensor.unregister_listener
(listener)Remove a listener callback added with register_listener(). KATCPSensor.wait
(condition_or_value[, timeout])Wait for the sensor to satisfy a condition. -
clear_listeners
()¶ Clear any registered listeners to updates from this sensor.
-
drop_sampling_strategy
()¶ Drop memorised sampling strategy for sensor, if any
Calling this method ensures that the sensor manager does not attempt to reapply a sampling strategy. It will not raise an error if no strategy has been set. Use
set_sampling_strategy()
to memorise a strategy again.
-
get_reading
(**kwargs)¶ Get a fresh sensor reading from the KATCP resource
Returns: reply : tornado Future resolving with KATCPSensorReading
objectNotes
As a side-effect this will update the reading stored in this object, and result in registered listeners being called.
-
get_status
(**kwargs)¶ Get a fresh sensor status from the KATCP resource
Returns: reply : tornado Future resolving with KATCPSensorReading
objectNotes
As a side-effect this will update the reading stored in this object, and result in registered listeners being called.
-
get_value
(**kwargs)¶ Get a fresh sensor value from the KATCP resource
Returns: reply : tornado Future resolving with KATCPSensorReading
objectNotes
As a side-effect this will update the reading stored in this object, and result in registered listeners being called.
-
name
¶ Name of this KATCPSensor
-
normalised_name
¶ Normalised name of this KATCPSensor that can be used as a python identifier
-
parent_name
¶ Name of the parent of this KATCPSensor
-
parse_value
(s_value)¶ Parse a value from a string.
Parameters: s_value : str
A string value to attempt to convert to a value for the sensor.
Returns: value : object
A value of a type appropriate to the sensor.
-
reading
¶ Most recently received sensor reading as KATCPSensorReading instance
-
register_listener
(listener, reading=False)¶ Add a callback function that is called when sensor value is updated.
The callback footprint is received_timestamp, timestamp, status, value.
Parameters: listener : function
Callback signature: if reading listener(katcp_sensor, reading) where katcp_sensor is this KATCPSensor instance reading is an instance of
KATCPSensorReading
.Callback signature: default, if not reading listener(received_timestamp, timestamp, status, value)
-
sampling_strategy
¶ Current sampling strategy
-
set
(timestamp, status, value)¶ Set sensor with a given received value, matches
katcp.Sensor.set()
-
set_formatted
(raw_timestamp, raw_status, raw_value, major)¶ Set sensor using KATCP string formatted inputs
Mirrors
katcp.Sensor.set_formatted()
.This implementation is empty. Will, during instantiation, be overridden by the set_formatted() method of a katcp.Sensor object.
-
set_sampling_strategy
(strategy)¶ Set current sampling strategy for sensor
Parameters: strategy : seq of str or str
As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: done : tornado Future that resolves when done or raises KATCPSensorError
-
set_strategy
(strategy, params=None)¶ Set current sampling strategy for sensor. Add this footprint for backwards compatibility.
Parameters: strategy : seq of str or str
As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
params : seq of str or str
(<strat_name>, [<strat_parm1>, …])
Returns: done : tornado Future that resolves when done or raises KATCPSensorError
-
set_value
(value, status=1, timestamp=None)¶ Set sensor value with optinal specification of status and timestamp
-
unregister_listener
(listener)¶ Remove a listener callback added with register_listener().
Parameters: listener : function
Reference to the callback function that should be removed
-
wait
(condition_or_value, timeout=None)¶ Wait for the sensor to satisfy a condition.
Parameters: condition_or_value : obj or callable, or seq of objs or callables
If obj, sensor.value is compared with obj. If callable, condition_or_value(reading) is called, and must return True if its condition is satisfied. Since the reading is passed in, the value, status, timestamp or received_timestamp attributes can all be used in the check. TODO: Sequences of conditions (use SensorTransitionWaiter thingum?)
timeout : float or None
The timeout in seconds (None means wait forever)
Returns: This command returns a tornado Future that resolves with True when the :
sensor value satisfies the condition. It will never resolve with False; :
if a timeout is given a TimeoutError happens instead. :
Raises: :class:`KATCPSensorError` :
If the sensor does not have a strategy set
:class:`tornado.gen.TimeoutError` :
If the sensor condition still fails after a stated timeout period
-
-
exception
katcp.resource.
KATCPSensorError
¶ Bases:
katcp.resource.KATCPResourceError
Raised if a problem occurred dealing with as KATCPSensor operation
-
class
katcp.resource.
KATCPSensorReading
¶ Bases:
katcp.resource.KATCPSensorReading
Sensor reading as a (received_timestamp, timestamp, istatus, value) tuple.
Attributes
KATCPSensorReading.received_timestamp
Alias for field number 0 KATCPSensorReading.timestamp
Alias for field number 1 KATCPSensorReading.istatus
Alias for field number 2 KATCPSensorReading.value
Alias for field number 3 Methods
KATCPSensorReading.count
(value)KATCPSensorReading.index
(value, [start, [stop]])Raises ValueError if the value is not present. -
status
¶ Returns the string representation of sensor status, eg ‘nominal’
-
-
class
katcp.resource.
KATCPSensorsManager
¶ Bases:
future.types.newobject.newobject
Sensor management class used by KATCPSensor. Abstracts communications details.
This class should arrange:
- A mechanism for setting sensor strategies
- A mechanism for polling a sensor value
- Keeping track of- and reapplying sensor strategies after reconnect, etc.
- Providing local time. This is doing to avoid direct calls to time.time, allowing accelerated time testing / simulation / dry-running
Methods
KATCPSensorsManager.drop_sampling_strategy
(…)Drop the sampling strategy for the named sensor from the cache KATCPSensorsManager.get_sampling_strategy
(…)Get the current sampling strategy for the named sensor KATCPSensorsManager.next
()KATCPSensorsManager.poll_sensor
(sensor_name)Poll sensor and arrange for sensor object to be updated KATCPSensorsManager.reapply_sampling_strategies
()Reapply all sensor strategies using cached values KATCPSensorsManager.set_sampling_strategy
(…)Set the sampling strategy for the named sensor KATCPSensorsManager.time
()Returns the current time (in seconds since UTC epoch) -
drop_sampling_strategy
(sensor_name)¶ Drop the sampling strategy for the named sensor from the cache
Calling
set_sampling_strategy()
requires the sensor manager to memorise the requested strategy so that it can automatically be reapplied. If the client is no longer interested in the sensor, or knows the sensor may be removed from the server, then it can use this method to ensure the manager forgets about the strategy. This method will not change the current strategy. No error is raised if there is no strategy to drop.Parameters: sensor_name : str
Name of the sensor (normal or escaped form)
-
get_sampling_strategy
(sensor_name)¶ Get the current sampling strategy for the named sensor
Parameters: sensor_name : str
Name of the sensor (normal or escaped form)
Returns: strategy : tornado Future that resolves with tuple of str
contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec
-
poll_sensor
(sensor_name)¶ Poll sensor and arrange for sensor object to be updated
Returns: done_future : tornado Future
Resolves when the poll is complete, or raises KATCPSensorError
-
reapply_sampling_strategies
()¶ Reapply all sensor strategies using cached values
Would typically be called when a connection is re-established. Should not raise errors when resetting strategies for sensors that no longer exist on the KATCP resource.
-
set_sampling_strategy
(sensor_name, strategy_and_parms)¶ Set the sampling strategy for the named sensor
Parameters: sensor_name : str
Name of the sensor
strategy : seq of str or str
As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: done : tornado Future that resolves when done or raises KATCPSensorError
Notes
It is recommended that implementations use
normalize_strategy_parameters()
to process the strategy_and_parms parameter, since it will deal with both string and list versions and makes sure that numbers are represented as strings in a consistent format.This method should arrange for the strategy to be set on the underlying network device or whatever other implementation is used. This strategy should also be automatically re-set if the device is reconnected, etc. If a strategy is set for a non-existing sensor, it should still cache the strategy and ensure that is applied whenever said sensor comes into existence. This allows an applications to pre-set strategies for sensors before synced / connected to a device.
-
time
()¶ Returns the current time (in seconds since UTC epoch)
-
class
katcp.resource.
SensorResultTuple
¶ Bases:
katcp.resource.SensorResultTuple
Per-sensor result of list_sensors() method
Attributes
SensorResultTuple.object
Alias for field number 0 SensorResultTuple.name
Alias for field number 1 SensorResultTuple.python_identifier
Alias for field number 2 SensorResultTuple.description
Alias for field number 3 SensorResultTuple.type
Alias for field number 4 SensorResultTuple.units
Alias for field number 5 SensorResultTuple.reading
Alias for field number 6 Methods
SensorResultTuple.count
(value)SensorResultTuple.index
(value, [start, [stop]])Raises ValueError if the value is not present.
-
katcp.resource.
escape_name
(name)¶ Escape sensor and request names to be valid Python identifiers.
-
katcp.resource.
normalize_strategy_parameters
(params)¶ Normalize strategy parameters to be a list of strings.
Parameters: params : (space-delimited) string or sequence of strings/numbers Parameters
expected by
SampleStrategy
object, in various forms, where the first parameter is the name of the strategy.Returns: params : tuple of strings
Strategy parameters as a list of strings
Concrete High-level KATCP Client API (resource_client)¶
-
class
katcp.resource_client.
AttrMappingProxy
(mapping, wrapper)¶ Bases:
katcp.resource_client.MappingProxy
Methods
AttrMappingProxy.get
(k[,d])AttrMappingProxy.items
()AttrMappingProxy.iteritems
()AttrMappingProxy.iterkeys
()AttrMappingProxy.itervalues
()AttrMappingProxy.keys
()AttrMappingProxy.values
()
-
class
katcp.resource_client.
ClientGroup
(name, clients)¶ Bases:
future.types.newobject.newobject
Create a group of similar clients.
Parameters: name : str
Name of the group of clients.
clients : list of
KATCPResource
objectsClients to put into the group.
Methods
ClientGroup.client_updated
(client)Called to notify this group that a client has been updated. ClientGroup.is_connected
()Indication of the connection state of all clients in the group ClientGroup.next
()ClientGroup.set_sampling_strategies
(**kwargs)Set sampling strategy for the sensors of all the group’s clients. ClientGroup.set_sampling_strategy
(**kwargs)Set sampling strategy for the sensors of all the group’s clients. ClientGroup.wait
(**kwargs)Wait for sensor present on all group clients to satisfy a condition. -
client_updated
(client)¶ Called to notify this group that a client has been updated.
-
is_connected
()¶ Indication of the connection state of all clients in the group
-
set_sampling_strategies
(**kwargs)¶ Set sampling strategy for the sensors of all the group’s clients.
Only sensors that match the specified filter are considered. See the KATCPResource.set_sampling_strategies docstring for parameter definitions and more info.
Returns: sensors_strategies : tornado Future
Resolves with a dict with client names as keys and with the value as another dict. The value dict is similar to the return value described in the KATCPResource.set_sampling_strategies docstring.
-
set_sampling_strategy
(**kwargs)¶ Set sampling strategy for the sensors of all the group’s clients.
Only sensors that match the specified filter are considered. See the KATCPResource.set_sampling_strategies docstring for parameter definitions and more info.
Returns: sensors_strategies : tornado Future
Resolves with a dict with client names as keys and with the value as another dict. The value dict is similar to the return value described in the KATCPResource.set_sampling_strategies docstring.
-
wait
(**kwargs)¶ Wait for sensor present on all group clients to satisfy a condition.
Parameters: sensor_name : string
The name of the sensor to check
condition_or_value : obj or callable, or seq of objs or callables
If obj, sensor.value is compared with obj. If callable, condition_or_value(reading) is called, and must return True if its condition is satisfied. Since the reading is passed in, the value, status, timestamp or received_timestamp attributes can all be used in the check.
timeout : float or None
The total timeout in seconds (None means wait forever)
quorum : None or int or float
The number of clients that are required to satisfy the condition, as either an explicit integer or a float between 0 and 1 indicating a fraction of the total number of clients, rounded up. If None, this means that all clients are required (the default). Be warned that a value of 1.0 (float) indicates all clients while a value of 1 (int) indicates a single client…
max_grace_period : float or None
After a quorum or initial timeout is reached, wait up to this long in an attempt to get the rest of the clients to satisfy condition as well (achieving effectively a full quorum if all clients behave)
Returns: This command returns a tornado Future that resolves with True when a :
quorum of clients satisfy the sensor condition, or False if a quorum :
is not reached after a given timeout period (including a grace period). :
Raises: :class:`KATCPSensorError` :
If any of the sensors do not have a strategy set, or if the named sensor is not present
-
-
class
katcp.resource_client.
GroupRequest
(group, name, description)¶ Bases:
future.types.newobject.newobject
Couroutine wrapper around a specific KATCP request for a group of clients.
Each available KATCP request supported by group has an associated
GroupRequest
object in the hierarchy. This wrapper is mainly for interactive convenience. It provides the KATCP request help string as a docstring accessible via IPython’s question mark operator.Parameters: Call parameters are all forwarded to the :class:`KATCPRequest` instance of each :
client in the group. :
Returns: Returns a tornado future that resolves with a :class:`GroupResults` instance that :
contains the replies of each client. If a particular client does not have the request, :
its result is None. :
Methods
GroupRequest.next
()
-
class
katcp.resource_client.
GroupResults
¶ Bases:
dict
The result of a group request.
This has a dictionary interface, with the client names as keys and the corresponding replies from each client as values. The replies are stored as
KATCPReply
objects, or are None for clients that did not support the request.The result will evaluate to a truthy value if all the requests succeeded, i.e.
if result: handle_success() else: handle_failure()
should work as expected.
Methods
GroupResults.clear
()GroupResults.copy
()GroupResults.fromkeys
(S[,v])v defaults to None. GroupResults.get
(k[,d])GroupResults.has_key
(k)GroupResults.items
()GroupResults.iteritems
()GroupResults.iterkeys
()GroupResults.itervalues
()GroupResults.keys
()GroupResults.pop
(k[,d])If key is not found, d is returned if given, otherwise KeyError is raised GroupResults.popitem
()2-tuple; but raise KeyError if D is empty. GroupResults.setdefault
(k[,d])GroupResults.update
([E, ]**F)If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k] GroupResults.values
()GroupResults.viewitems
()GroupResults.viewkeys
()GroupResults.viewvalues
()-
succeeded
¶ True if katcp request succeeded on all clients.
-
-
class
katcp.resource_client.
KATCPClientResource
(resource_spec, parent=None, logger=<logging.Logger object>)¶ Bases:
katcp.resource.KATCPResource
Class managing a client connection to a single KATCP resource
Inspects the KATCP interface of the resources, exposing sensors and requests as per the
katcp.resource.KATCPResource
API. Can also operate without exposingMethods
KATCPClientResource.drop_sampling_strategy
(…)Drop the sampling strategy for the named sensor from the cache KATCPClientResource.inspecting_client_factory
(…)Return an instance of ReplyWrappedInspectingClientAsync
or similarKATCPClientResource.is_active
()KATCPClientResource.is_connected
()Indication of the connection state KATCPClientResource.list_sensors
([filter, …])List sensors available on this resource matching certain criteria. KATCPClientResource.next
()KATCPClientResource.set_active
(active)KATCPClientResource.set_ioloop
([ioloop])Set the tornado ioloop to use KATCPClientResource.set_sampling_strategies
(…)Set a strategy for all sensors matching the filter, including unseen sensors The strategy should persist across sensor disconnect/reconnect. KATCPClientResource.set_sampling_strategy
(…)Set a strategy for a sensor even if it is not yet known. KATCPClientResource.set_sensor_listener
(**kwargs)Set a sensor listener for a sensor even if it is not yet known The listener registration should persist across sensor disconnect/reconnect. KATCPClientResource.start
()Start the client and connect KATCPClientResource.stop
()KATCPClientResource.until_not_synced
([timeout])Convenience method to wait (with Future) until client is not synced KATCPClientResource.until_state
(state[, timeout])Future that resolves when a certain client state is attained KATCPClientResource.until_stopped
([timeout])Return future that resolves when the inspecting client has stopped KATCPClientResource.until_synced
([timeout])Convenience method to wait (with Future) until client is synced KATCPClientResource.wait
(**kwargs)Wait for a sensor in this resource to satisfy a condition. KATCPClientResource.wait_connected
([timeout])Future that resolves when the state is not ‘disconnected’. -
MAX_LOOP_LATENCY
= 0.03¶ When doing potentially tight loops in coroutines yield tornado.gen.moment after this much time. This is a suggestion for methods to use.
-
drop_sampling_strategy
(sensor_name)¶ Drop the sampling strategy for the named sensor from the cache
Calling
set_sampling_strategy()
requires the requested strategy to be memorised so that it can automatically be reapplied. This method causes the strategy to be forgotten. There is no change to the current strategy. No error is raised if there is no strategy to drop.Parameters: sensor_name : str
Name of the sensor
-
inspecting_client_factory
(host, port, ioloop_set_to)¶ Return an instance of
ReplyWrappedInspectingClientAsync
or similarProvided to ease testing. Dynamically overriding this method after instantiation but before start() is called allows for deep brain surgery. See
katcp.fake_clients.fake_inspecting_client_factory
-
is_connected
()¶ Indication of the connection state
Returns True if state is not “disconnected”, i.e “syncing” or “synced”
-
list_sensors
(filter='', strategy=False, status='', use_python_identifiers=True, tuple=False, refresh=False)¶ List sensors available on this resource matching certain criteria.
Parameters: filter : string, optional
Filter each returned sensor’s name against this regexp if specified. To ease the dichotomy between Python identifier names and actual sensor names, the default is to search on Python identifier names rather than KATCP sensor names, unless use_python_identifiers below is set to False. Note that the sensors of subordinate KATCPResource instances may have inconsistent names and Python identifiers, better to always search on Python identifiers in this case.
strategy : {False, True}, optional
Only list sensors with a set strategy if True
status : string, optional
Filter each returned sensor’s status against this regexp if given
use_python_identifiers : {True, False}, optional
Match on python identifiers even the the KATCP name is available.
tuple : {True, False}, optional, Default: False
Return backwards compatible tuple instead of SensorResultTuples
refresh : {True, False}, optional, Default: False
If set the sensor values will be refreshed with get_value before returning the results.
Returns: sensors : list of SensorResultTuples, or list of tuples
List of matching sensors presented as named tuples. The object field is the
KATCPSensor
object associated with the sensor. Note that the name of the object may not match name if it originates from a subordinate device.
-
set_ioloop
(ioloop=None)¶ Set the tornado ioloop to use
Defaults to tornado.ioloop.IOLoop.current() if set_ioloop() is not called or if ioloop=None. Must be called before start()
-
set_sampling_strategies
(**kwargs)¶ Set a strategy for all sensors matching the filter, including unseen sensors The strategy should persist across sensor disconnect/reconnect.
- filter : str
- Filter for sensor names
- strategy_and_params : seq of str or str
- As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: done : tornado Future
Resolves when done
-
set_sampling_strategy
(**kwargs)¶ Set a strategy for a sensor even if it is not yet known. The strategy should persist across sensor disconnect/reconnect.
- sensor_name : str
- Name of the sensor
- strategy_and_params : seq of str or str
- As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: done : tornado Future
Resolves when done
-
set_sensor_listener
(**kwargs)¶ Set a sensor listener for a sensor even if it is not yet known The listener registration should persist across sensor disconnect/reconnect.
- sensor_name : str
- Name of the sensor
- listener : callable
- Listening callable that will be registered on the named sensor when it becomes
available. Callable as for
KATCPSensor.register_listener()
-
start
()¶ Start the client and connect
-
until_not_synced
(timeout=None)¶ Convenience method to wait (with Future) until client is not synced
-
until_state
(state, timeout=None)¶ Future that resolves when a certain client state is attained
Parameters: state : str
Desired state, one of (“disconnected”, “syncing”, “synced”)
timeout: float :
Timeout for operation in seconds.
-
until_stopped
(timeout=None)¶ Return future that resolves when the inspecting client has stopped
See the DeviceClient.until_stopped docstring for parameter definitions and more info.
-
until_synced
(timeout=None)¶ Convenience method to wait (with Future) until client is synced
-
wait_connected
(timeout=None)¶ Future that resolves when the state is not ‘disconnected’.
-
-
class
katcp.resource_client.
KATCPClientResourceContainer
(resources_spec, logger=<logging.Logger object>)¶ Bases:
katcp.resource.KATCPResource
Class for containing multiple
KATCPClientResource
instances.Provides aggregate sensor and req attributes containing the union of all the sensors in requests in the contained resources. Names are prefixed with <resname>_, where <resname> is the name of the resource to which the sensor / request belongs except for aggregate sensors that starts with
agg_
.Methods
KATCPClientResourceContainer.add_child_resource_client
(…)Add a resource client to the container and start the resource connection KATCPClientResourceContainer.add_group
(…)Add a new ClientGroup
to container groups member.KATCPClientResourceContainer.client_resource_factory
(…)Return an instance of KATCPClientResource
or similarKATCPClientResourceContainer.is_active
()KATCPClientResourceContainer.is_connected
()Indication of the connection state of all children KATCPClientResourceContainer.list_sensors
([…])List sensors available on this resource matching certain criteria. KATCPClientResourceContainer.next
()KATCPClientResourceContainer.set_active
(active)KATCPClientResourceContainer.set_ioloop
([ioloop])Set the tornado ioloop to use KATCPClientResourceContainer.set_sampling_strategies
(…)Set sampling strategies for filtered sensors - these sensors have to exists. KATCPClientResourceContainer.set_sampling_strategy
(…)Set sampling strategies for the specific sensor - this sensor has to exist KATCPClientResourceContainer.set_sensor_listener
(…)Set listener for the specific sensor - this sensor has to exists. KATCPClientResourceContainer.start
()Start and connect all the subordinate clients KATCPClientResourceContainer.stop
()Stop all child resources KATCPClientResourceContainer.until_all_children_in_state
(…)Return a tornado Future; resolves when all clients are in specified state KATCPClientResourceContainer.until_any_child_in_state
(state)Return a tornado Future; resolves when any client is in specified state KATCPClientResourceContainer.until_not_synced
(…)Return a tornado Future; resolves when any subordinate client is not synced KATCPClientResourceContainer.until_stopped
([…])Return dict of futures that resolve when each child resource has stopped KATCPClientResourceContainer.until_synced
(…)Return a tornado Future; resolves when all subordinate clients are synced KATCPClientResourceContainer.wait
(…[, timeout])Wait for a sensor in this resource to satisfy a condition. -
add_child_resource_client
(res_name, res_spec)¶ Add a resource client to the container and start the resource connection
-
add_group
(group_name, group_client_names)¶ Add a new
ClientGroup
to container groups member.Add the group named group_name with sequence of client names to the container groups member. From there it will be wrapped appropriately in the higher-level thread-safe container.
-
client_resource_factory
(res_spec, parent, logger)¶ Return an instance of
KATCPClientResource
or similarProvided to ease testing. Overriding this method allows deep brain surgery. See
katcp.fake_clients.fake_KATCP_client_resource_factory()
-
is_connected
()¶ Indication of the connection state of all children
-
list_sensors
(filter='', strategy=False, status='', use_python_identifiers=True, tuple=False, refresh=False)¶ List sensors available on this resource matching certain criteria.
Parameters: filter : string, optional
Filter each returned sensor’s name against this regexp if specified. To ease the dichotomy between Python identifier names and actual sensor names, the default is to search on Python identifier names rather than KATCP sensor names, unless use_python_identifiers below is set to False. Note that the sensors of subordinate KATCPResource instances may have inconsistent names and Python identifiers, better to always search on Python identifiers in this case.
strategy : {False, True}, optional
Only list sensors with a set strategy if True
status : string, optional
Filter each returned sensor’s status against this regexp if given
use_python_identifiers : {True, False}, optional
Match on python identifiers even the the KATCP name is available.
tuple : {True, False}, optional, Default: False
Return backwards compatible tuple instead of SensorResultTuples
refresh : {True, False}, optional, Default: False
If set the sensor values will be refreshed with get_value before returning the results.
Returns: sensors : list of SensorResultTuples, or list of tuples
List of matching sensors presented as named tuples. The object field is the
KATCPSensor
object associated with the sensor. Note that the name of the object may not match name if it originates from a subordinate device.
-
set_ioloop
(ioloop=None)¶ Set the tornado ioloop to use
Defaults to tornado.ioloop.IOLoop.current() if set_ioloop() is not called or if ioloop=None. Must be called before start()
-
set_sampling_strategies
(**kwargs)¶ Set sampling strategies for filtered sensors - these sensors have to exists.
-
set_sampling_strategy
(**kwargs)¶ Set sampling strategies for the specific sensor - this sensor has to exist
-
set_sensor_listener
(**kwargs)¶ Set listener for the specific sensor - this sensor has to exists.
-
start
()¶ Start and connect all the subordinate clients
-
stop
()¶ Stop all child resources
-
until_all_children_in_state
(**kwargs)¶ Return a tornado Future; resolves when all clients are in specified state
-
until_any_child_in_state
(state, timeout=None)¶ Return a tornado Future; resolves when any client is in specified state
-
until_not_synced
(**kwargs)¶ Return a tornado Future; resolves when any subordinate client is not synced
-
until_stopped
(timeout=None)¶ Return dict of futures that resolve when each child resource has stopped
See the DeviceClient.until_stopped docstring for parameter definitions and more info.
-
until_synced
(**kwargs)¶ Return a tornado Future; resolves when all subordinate clients are synced
-
wait
(sensor_name, condition_or_value, timeout=5)¶ Wait for a sensor in this resource to satisfy a condition.
Parameters: sensor_name : string
The name of the sensor to check
condition_or_value : obj or callable, or seq of objs or callables
If obj, sensor.value is compared with obj. If callable, condition_or_value(reading) is called, and must return True if its condition is satisfied. Since the reading is passed in, the value, status, timestamp or received_timestamp attributes can all be used in the check.
timeout : float or None
The timeout in seconds (None means wait forever)
Returns: This command returns a tornado Future that resolves with True when the :
sensor value satisfies the condition, or False if the condition is :
still not satisfied after a given timeout period. :
Raises: :class:`KATCPSensorError` :
If the sensor does not have a strategy set, or if the named sensor is not present
-
-
class
katcp.resource_client.
KATCPClientResourceRequest
(request_description, client, is_active=<function <lambda>>)¶ Bases:
katcp.resource.KATCPRequest
Callable wrapper around a KATCP request
Methods
KATCPClientResourceRequest.is_active
()True if resource for this request is active KATCPClientResourceRequest.issue_request
(…)Issue the wrapped request to the server. KATCPClientResourceRequest.next
()-
issue_request
(*args, **kwargs)¶ Issue the wrapped request to the server.
Parameters: *args : list of objects
Arguments to pass on to the request.
Keyword Arguments: timeout : float or None, optional
Timeout after this amount of seconds (keyword argument).
mid : None or int, optional
Message identifier to use for the request message. If None, use either auto-incrementing value or no mid depending on the KATCP protocol version (mid’s were only introduced with KATCP v5) and the value of the use_mid argument. Defaults to None.
use_mid : bool
Use a mid for the request if True.
Returns: future object that resolves with an :class:`katcp.resource.KATCPReply` :
instance :
-
-
class
katcp.resource_client.
KATCPClientResourceSensorsManager
(inspecting_client, resource_name, logger=<logging.Logger object>)¶ Bases:
future.types.newobject.newobject
Implementation of KATSensorsManager ABC for a directly-connected client
Assumes that all methods are called from the same ioloop context
Methods
KATCPClientResourceSensorsManager.drop_sampling_strategy
(…)Drop the sampling strategy for the named sensor from the cache KATCPClientResourceSensorsManager.get_sampling_strategy
(…)Get the current sampling strategy for the named sensor KATCPClientResourceSensorsManager.next
()KATCPClientResourceSensorsManager.poll_sensor
(…)Poll sensor and arrange for sensor object to be updated KATCPClientResourceSensorsManager.reapply_sampling_strategies
(…)Reapply all sensor strategies using cached values KATCPClientResourceSensorsManager.sensor_factory
(…)KATCPClientResourceSensorsManager.set_sampling_strategy
(…)Set the sampling strategy for the named sensor -
drop_sampling_strategy
(sensor_name)¶ Drop the sampling strategy for the named sensor from the cache
Calling
set_sampling_strategy()
requires the sensor manager to memorise the requested strategy so that it can automatically be reapplied. If the client is no longer interested in the sensor, or knows the sensor may be removed from the server, then it can use this method to ensure the manager forgets about the strategy. This method will not change the current strategy. No error is raised if there is no strategy to drop.Parameters: sensor_name : str
Name of the sensor (normal or escaped form)
-
get_sampling_strategy
(sensor_name)¶ Get the current sampling strategy for the named sensor
Parameters: sensor_name : str
Name of the sensor (normal or escaped form)
Returns: strategy : tuple of str
contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec
-
poll_sensor
(**kwargs)¶ Poll sensor and arrange for sensor object to be updated
Returns: done_future : tornado Future
Resolves when the poll is complete, or raises KATCPSensorError
-
reapply_sampling_strategies
(**kwargs)¶ Reapply all sensor strategies using cached values
-
set_sampling_strategy
(**kwargs)¶ Set the sampling strategy for the named sensor
Parameters: sensor_name : str
Name of the sensor
strategy_and_params : seq of str or str
As tuple contains (<strat_name>, [<strat_parm1>, …]) where the strategy names and parameters are as defined by the KATCP spec. As str contains the same elements in space-separated form.
Returns: sensor_strategy : tuple
(success, info) with
- success : bool
True if setting succeeded for this sensor, else False
- info : tuple
Normalised sensor strategy and parameters as tuple if success == True else, sys.exc_info() tuple for the error that occurred.
-
-
class
katcp.resource_client.
MappingProxy
(mapping, wrapper)¶ Bases:
_abcoll.Mapping
Methods
MappingProxy.get
(k[,d])MappingProxy.items
()MappingProxy.iteritems
()MappingProxy.iterkeys
()MappingProxy.itervalues
()MappingProxy.keys
()MappingProxy.values
()
-
class
katcp.resource_client.
ReplyWrappedInspectingClientAsync
(host, port, ioloop=None, initial_inspection=None, auto_reconnect=True, logger=<logging.Logger object>)¶ Bases:
katcp.inspecting_client.InspectingClientAsync
Adds wrapped_request() method that wraps reply in a KATCPReply
Methods
ReplyWrappedInspectingClientAsync.close
()ReplyWrappedInspectingClientAsync.connect
(…)Connect to KATCP interface, starting what is needed ReplyWrappedInspectingClientAsync.future_check_request
(…)Check if the request exists. ReplyWrappedInspectingClientAsync.future_check_sensor
(…)Check if the sensor exists. ReplyWrappedInspectingClientAsync.future_get_request
(…)Get the request object. ReplyWrappedInspectingClientAsync.future_get_sensor
(…)Get the sensor object. ReplyWrappedInspectingClientAsync.handle_sensor_value
()Handle #sensor-value informs just like #sensor-status informs ReplyWrappedInspectingClientAsync.inform_hook_client_factory
(…)Return an instance of _InformHookDeviceClient
or similarReplyWrappedInspectingClientAsync.inspect
(…)Inspect device requests and sensors, update model. ReplyWrappedInspectingClientAsync.inspect_requests
(…)Inspect all or one requests on the device. ReplyWrappedInspectingClientAsync.inspect_sensors
(…)Inspect all or one sensor on the device. ReplyWrappedInspectingClientAsync.is_connected
()Connection status. ReplyWrappedInspectingClientAsync.join
([timeout])ReplyWrappedInspectingClientAsync.next
()ReplyWrappedInspectingClientAsync.preset_protocol_flags
(…)Preset server protocol flags. ReplyWrappedInspectingClientAsync.reply_wrapper
(x)ReplyWrappedInspectingClientAsync.request_factory
alias of katcp.inspecting_client.Request
ReplyWrappedInspectingClientAsync.sensor_factory
alias of katcp.core.Sensor
ReplyWrappedInspectingClientAsync.set_ioloop
(ioloop)ReplyWrappedInspectingClientAsync.set_state_callback
(cb)Set user callback for state changes ReplyWrappedInspectingClientAsync.simple_request
(…)Create and send a request to the server. ReplyWrappedInspectingClientAsync.start
([…])Note: always call stop() and wait until_stopped() when you are done with the container to make sure the container cleans up correctly. ReplyWrappedInspectingClientAsync.stop
([timeout])ReplyWrappedInspectingClientAsync.until_connected
([…])ReplyWrappedInspectingClientAsync.until_data_synced
([…])ReplyWrappedInspectingClientAsync.until_not_synced
([…])ReplyWrappedInspectingClientAsync.until_state
(…)Wait until state is desired_state, InspectingClientStateType instance ReplyWrappedInspectingClientAsync.until_stopped
([…])Return future that resolves when the client has stopped ReplyWrappedInspectingClientAsync.until_synced
([…])ReplyWrappedInspectingClientAsync.update_sensor
(…)ReplyWrappedInspectingClientAsync.wrapped_request
(…)Create and send a request to the server. -
wrapped_request
(request, *args, **kwargs)¶ Create and send a request to the server.
This method implements a very small subset of the options possible to send an request. It is provided as a shortcut to sending a simple wrapped request.
Parameters: request : str
The request to call.
*args : list of objects
Arguments to pass on to the request.
Keyword Arguments: timeout : float or None, optional
Timeout after this amount of seconds (keyword argument).
mid : None or int, optional
Message identifier to use for the request message. If None, use either auto-incrementing value or no mid depending on the KATCP protocol version (mid’s were only introduced with KATCP v5) and the value of the use_mid argument. Defaults to None.
use_mid : bool
Use a mid for the request if True.
Returns: future object that resolves with the :
:meth:`katcp.client.DeviceClient.future_request` response wrapped in :
self.reply_wrapper :
-
-
class
katcp.resource_client.
ThreadSafeKATCPClientGroupWrapper
(subject, ioloop_wrapper)¶ Bases:
katcp.ioloop_manager.ThreadSafeMethodAttrWrapper
Thread safe wrapper for
ClientGroup
Methods
ThreadSafeKATCPClientGroupWrapper.next
()
-
class
katcp.resource_client.
ThreadSafeKATCPClientResourceRequestWrapper
(subject, ioloop_wrapper)¶ Bases:
katcp.ioloop_manager.ThreadSafeMethodAttrWrapper
Methods
ThreadSafeKATCPClientResourceRequestWrapper.next
()
-
class
katcp.resource_client.
ThreadSafeKATCPClientResourceWrapper
(subject, ioloop_wrapper)¶ Bases:
katcp.ioloop_manager.ThreadSafeMethodAttrWrapper
Should work with both KATCPClientResource or KATCPClientResourceContainer
Methods
ThreadSafeKATCPClientResourceWrapper.next
()
-
class
katcp.resource_client.
ThreadSafeKATCPSensorWrapper
(subject, ioloop_wrapper)¶ Bases:
katcp.ioloop_manager.ThreadSafeMethodAttrWrapper
Methods
ThreadSafeKATCPSensorWrapper.next
()
-
katcp.resource_client.
list_sensors
(*args, **kwargs)¶ Helper for implementing
katcp.resource.KATCPResource.list_sensors()
Parameters: sensor_items : tuple of sensor-item tuples
As would be returned the items() method of a dict containing KATCPSensor objects keyed by Python-identifiers.
parent_class: KATCPClientResource or KATCPClientResourceContainer :
Is used for prefix calculation
Rest of parameters as for :meth:`katcp.resource.KATCPResource.list_sensors` :
-
katcp.resource_client.
monitor_resource_sync_state
(*args, **kwargs)¶ Coroutine that monitors a KATCPResource’s sync state.
Calls callback(True/False) whenever the resource becomes synced or unsynced. Will always do an initial callback(False) call. Exits without calling callback() if exit_event is set.
Warning: set the monitor’s exit_event before stopping the resources being monitored, otherwise it could result in a memory leak. The until_synced() or until_not_synced() methods could keep a reference to the resource alive.
-
katcp.resource_client.
transform_future
(transformation, future)¶ Returns a new future that will resolve with a transformed value.
Takes the resolution value of future and applies “transformation(*future.result())” to it before setting the result of the new future with the transformed value. If future() resolves with an exception, it is passed through to the new future.
Assumes future is a tornado Future.
Sampling¶
Strategies for sampling sensor values.
-
class
katcp.sampling.
SampleAuto
(inform_callback, sensor, *params, **kwargs)¶ Bases:
katcp.sampling.SampleStrategy
Strategy which sends updates whenever the sensor itself is updated.
Methods
SampleAuto.attach
()Attach strategy to its sensor and send initial update. SampleAuto.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SampleAuto.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SampleAuto.detach
()Detach strategy from its sensor. SampleAuto.get_sampling
()The Strategy constant for this sampling strategy. SampleAuto.get_sampling_formatted
()The current sampling strategy and parameters. SampleAuto.get_strategy
(strategyName, …)Factory method to create a strategy object. SampleAuto.inform
(reading)Inform strategy creator of the sensor status. SampleAuto.start
()Start operating the strategy. SampleAuto.update
(sensor, reading)Callback used by the sensor’s notify() method. -
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
update
(sensor, reading)¶ Callback used by the sensor’s notify() method.
This update method is called whenever the sensor value is set so sensor will contain the right info. Note that the strategy does not really need to be passed a sensor because it already has a handle to it, but receives it due to the generic observer mechanism.
Sub-classes should override this method or
start()
to provide the necessary sampling strategy. Sub-classes should also ensure thatupdate()
is thread-safe; an easy way to do this is by using the @update_in_ioloop decorator.Parameters: sensor : Sensor object
The sensor which was just updated.
reading : (timestamp, status, value) tuple
Sensor reading as would be returned by sensor.read()
-
-
class
katcp.sampling.
SampleDifferential
(inform_callback, sensor, *params, **kwargs)¶ Bases:
katcp.sampling.SampleStrategy
Differential sampling strategy for integer and float sensors.
Sends updates only when the value has changed by more than some specified threshold, or the status changes.
Methods
SampleDifferential.attach
()Attach strategy to its sensor and send initial update. SampleDifferential.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SampleDifferential.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SampleDifferential.detach
()Detach strategy from its sensor. SampleDifferential.get_sampling
()The Strategy constant for this sampling strategy. SampleDifferential.get_sampling_formatted
()The current sampling strategy and parameters. SampleDifferential.get_strategy
(…)Factory method to create a strategy object. SampleDifferential.inform
(reading)Inform strategy creator of the sensor status. SampleDifferential.start
()Start operating the strategy. SampleDifferential.update
(sensor, reading)Callback used by the sensor’s notify() method. -
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
update
(sensor, reading)¶ Callback used by the sensor’s notify() method.
This update method is called whenever the sensor value is set so sensor will contain the right info. Note that the strategy does not really need to be passed a sensor because it already has a handle to it, but receives it due to the generic observer mechanism.
Sub-classes should override this method or
start()
to provide the necessary sampling strategy. Sub-classes should also ensure thatupdate()
is thread-safe; an easy way to do this is by using the @update_in_ioloop decorator.Parameters: sensor : Sensor object
The sensor which was just updated.
reading : (timestamp, status, value) tuple
Sensor reading as would be returned by sensor.read()
-
-
class
katcp.sampling.
SampleDifferentialRate
(inform_callback, sensor, *params, **kwargs)¶ Bases:
katcp.sampling.SampleEventRate
Differential rate sampling strategy.
Report the value whenever it changes by more than difference from the last reported value or if more than longest_period seconds have passed since the last reported update. However, do not report the value until shortest_period seconds have passed since the last reported update. The behaviour if shortest_period is greater than longest_period is undefined. May only be implemented for float and integer sensors.
Methods
SampleDifferentialRate.attach
()Attach strategy to its sensor and send initial update. SampleDifferentialRate.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SampleDifferentialRate.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SampleDifferentialRate.detach
()Detach strategy from its sensor. SampleDifferentialRate.get_sampling
()The Strategy constant for this sampling strategy. SampleDifferentialRate.get_sampling_formatted
()The current sampling strategy and parameters. SampleDifferentialRate.get_strategy
(…)Factory method to create a strategy object. SampleDifferentialRate.inform
(reading)Inform strategy creator of the sensor status. SampleDifferentialRate.start
()Start operating the strategy. SampleDifferentialRate.update
(sensor, reading)Callback used by the sensor’s notify() method. -
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
-
class
katcp.sampling.
SampleEvent
(inform_callback, sensor, *params, **kwargs)¶ Bases:
katcp.sampling.SampleEventRate
Strategy which sends updates when the sensor value or status changes.
Since SampleEvent is just a special case of SampleEventRate, we use SampleEventRate with the appropriate default values to implement SampleEvent.
Methods
SampleEvent.attach
()Attach strategy to its sensor and send initial update. SampleEvent.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SampleEvent.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SampleEvent.detach
()Detach strategy from its sensor. SampleEvent.get_sampling
()The Strategy constant for this sampling strategy. SampleEvent.get_sampling_formatted
()The current sampling strategy and parameters. SampleEvent.get_strategy
(strategyName, …)Factory method to create a strategy object. SampleEvent.inform
(reading)Inform strategy creator of the sensor status. SampleEvent.start
()Start operating the strategy. SampleEvent.update
(sensor, reading)Callback used by the sensor’s notify() method. -
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
-
class
katcp.sampling.
SampleEventRate
(inform_callback, sensor, *params, **kwargs)¶ Bases:
katcp.sampling.SampleStrategy
Event rate sampling strategy.
Report the sensor value whenever it changes or if more than longest_period seconds have passed since the last reported update. However, do not report the value if less than shortest_period seconds have passed since the last reported update.
Methods
SampleEventRate.attach
()Attach strategy to its sensor and send initial update. SampleEventRate.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SampleEventRate.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SampleEventRate.detach
()Detach strategy from its sensor. SampleEventRate.get_sampling
()The Strategy constant for this sampling strategy. SampleEventRate.get_sampling_formatted
()The current sampling strategy and parameters. SampleEventRate.get_strategy
(strategyName, …)Factory method to create a strategy object. SampleEventRate.inform
(reading)Inform strategy creator of the sensor status. SampleEventRate.start
()Start operating the strategy. SampleEventRate.update
(sensor, reading)Callback used by the sensor’s notify() method. -
cancel_timeouts
()¶ Override this method to cancel any outstanding ioloop timeouts.
-
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
inform
(reading)¶ Inform strategy creator of the sensor status.
-
start
()¶ Start operating the strategy.
Subclasses that override start() should call the super method before it does anything that uses the ioloop. This will attach to the sensor as an observer if
OBSERVE_UPDATES
is True, and sets_ioloop_thread_id
using thread.get_ident().
-
update
(sensor, reading)¶ Callback used by the sensor’s notify() method.
This update method is called whenever the sensor value is set so sensor will contain the right info. Note that the strategy does not really need to be passed a sensor because it already has a handle to it, but receives it due to the generic observer mechanism.
Sub-classes should override this method or
start()
to provide the necessary sampling strategy. Sub-classes should also ensure thatupdate()
is thread-safe; an easy way to do this is by using the @update_in_ioloop decorator.Parameters: sensor : Sensor object
The sensor which was just updated.
reading : (timestamp, status, value) tuple
Sensor reading as would be returned by sensor.read()
-
-
class
katcp.sampling.
SampleNone
(inform_callback, sensor, *params, **kwargs)¶ Bases:
katcp.sampling.SampleStrategy
Sampling strategy which never sends any updates.
Methods
SampleNone.attach
()Attach strategy to its sensor and send initial update. SampleNone.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SampleNone.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SampleNone.detach
()Detach strategy from its sensor. SampleNone.get_sampling
()The Strategy constant for this sampling strategy. SampleNone.get_sampling_formatted
()The current sampling strategy and parameters. SampleNone.get_strategy
(strategyName, …)Factory method to create a strategy object. SampleNone.inform
(reading)Inform strategy creator of the sensor status. SampleNone.start
()Start operating the strategy. SampleNone.update
(sensor, reading)Callback used by the sensor’s notify() method. -
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
start
()¶ Start operating the strategy.
Subclasses that override start() should call the super method before it does anything that uses the ioloop. This will attach to the sensor as an observer if
OBSERVE_UPDATES
is True, and sets_ioloop_thread_id
using thread.get_ident().
-
-
class
katcp.sampling.
SamplePeriod
(inform_callback, sensor, *params, **kwargs)¶ Bases:
katcp.sampling.SampleStrategy
Periodic sampling strategy.
Methods
SamplePeriod.attach
()Attach strategy to its sensor and send initial update. SamplePeriod.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SamplePeriod.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SamplePeriod.detach
()Detach strategy from its sensor. SamplePeriod.get_sampling
()The Strategy constant for this sampling strategy. SamplePeriod.get_sampling_formatted
()The current sampling strategy and parameters. SamplePeriod.get_strategy
(strategyName, …)Factory method to create a strategy object. SamplePeriod.inform
(reading)Inform strategy creator of the sensor status. SamplePeriod.start
()Start operating the strategy. SamplePeriod.update
(sensor, reading)Callback used by the sensor’s notify() method. -
cancel_timeouts
()¶ Override this method to cancel any outstanding ioloop timeouts.
-
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
start
()¶ Start operating the strategy.
Subclasses that override start() should call the super method before it does anything that uses the ioloop. This will attach to the sensor as an observer if
OBSERVE_UPDATES
is True, and sets_ioloop_thread_id
using thread.get_ident().
-
-
class
katcp.sampling.
SampleStrategy
(inform_callback, sensor, *params, **kwargs)¶ Bases:
object
Base class for strategies for sampling sensors.
Parameters: inform_callback : callable, signature inform_callback(sensor_obj, reading)
Callback to receive inform messages.
sensor : Sensor object
Sensor to sample.
params : list of objects
Custom sampling parameters.
Methods
SampleStrategy.attach
()Attach strategy to its sensor and send initial update. SampleStrategy.cancel
()Detach strategy from its sensor and cancel ioloop callbacks. SampleStrategy.cancel_timeouts
()Override this method to cancel any outstanding ioloop timeouts. SampleStrategy.detach
()Detach strategy from its sensor. SampleStrategy.get_sampling
()The Strategy constant for this sampling strategy. SampleStrategy.get_sampling_formatted
()The current sampling strategy and parameters. SampleStrategy.get_strategy
(strategyName, …)Factory method to create a strategy object. SampleStrategy.inform
(reading)Inform strategy creator of the sensor status. SampleStrategy.start
()Start operating the strategy. SampleStrategy.update
(sensor, reading)Callback used by the sensor’s notify() method. -
OBSERVE_UPDATES
= False¶ True if a strategy must be attached to its sensor as an observer
-
attach
()¶ Attach strategy to its sensor and send initial update.
-
cancel
()¶ Detach strategy from its sensor and cancel ioloop callbacks.
-
cancel_timeouts
()¶ Override this method to cancel any outstanding ioloop timeouts.
-
detach
()¶ Detach strategy from its sensor.
-
get_sampling
()¶ The Strategy constant for this sampling strategy.
Sub-classes should implement this method and return the appropriate constant.
Returns: strategy : Strategy constant
The strategy type constant for this strategy.
-
get_sampling_formatted
()¶ The current sampling strategy and parameters.
The strategy is returned as a byte string and the values in the parameter list are formatted as byte strings using the formatter for this sensor type.
Returns: strategy_name : bytes
KATCP name for the strategy.
params : list of bytes
KATCP formatted parameters for the strategy.
-
classmethod
get_strategy
(strategyName, inform_callback, sensor, *params, **kwargs)¶ Factory method to create a strategy object.
Parameters: strategyName : str or bytes
Name of strategy.
inform_callback : callable, signature inform_callback(sensor, reading)
Callback to receive inform messages.
sensor : Sensor object
Sensor to sample.
params : list of objects
Custom sampling parameters for specified strategy.
Keyword Arguments: ioloop : tornado.ioloop.IOLoop instance, optional
Tornado ioloop to use, otherwise tornado.ioloop.IOLoop.current()
Returns: strategy :
SampleStrategy
objectThe created sampling strategy.
-
inform
(reading)¶ Inform strategy creator of the sensor status.
-
start
()¶ Start operating the strategy.
Subclasses that override start() should call the super method before it does anything that uses the ioloop. This will attach to the sensor as an observer if
OBSERVE_UPDATES
is True, and sets_ioloop_thread_id
using thread.get_ident().
-
update
(sensor, reading)¶ Callback used by the sensor’s notify() method.
This update method is called whenever the sensor value is set so sensor will contain the right info. Note that the strategy does not really need to be passed a sensor because it already has a handle to it, but receives it due to the generic observer mechanism.
Sub-classes should override this method or
start()
to provide the necessary sampling strategy. Sub-classes should also ensure thatupdate()
is thread-safe; an easy way to do this is by using the @update_in_ioloop decorator.Parameters: sensor : Sensor object
The sensor which was just updated.
reading : (timestamp, status, value) tuple
Sensor reading as would be returned by sensor.read()
-
-
katcp.sampling.
update_in_ioloop
(update)¶ Decorator that ensures an update() method is run in the tornado ioloop.
Does this by checking the thread identity. Requires that the object to which the method is bound has the attributes
_ioloop_thread_id
(the result of thread.get_ident() in the ioloop thread) andioloop
(the ioloop instance in use). Also assumes the signature update(self, sensor, reading) for the method.
KATCP Server API (server)¶
Servers for the KAT device control language.
-
class
katcp.server.
AsyncDeviceServer
(*args, **kwargs)¶ Bases:
katcp.server.DeviceServer
DeviceServer that is automatically configured for async use.
Same as instantiating a
DeviceServer
instance and calling methods set_concurrency_options(thread_safe=False, handler_thread=False) and set_ioloop(tornado.ioloop.IOLoop.current()) before starting.Methods
AsyncDeviceServer.add_sensor
(sensor)Add a sensor to the device. AsyncDeviceServer.build_state
()Return build state string of the form name-major.minor[(a|b|rc)n]. AsyncDeviceServer.clear_strategies
(client_conn)Clear the sensor strategies of a client connection. AsyncDeviceServer.create_exception_reply_and_log
(…)AsyncDeviceServer.create_log_inform
(…[, …])Create a katcp logging inform message. AsyncDeviceServer.get_sensor
(sensor_name)Fetch the sensor with the given name. AsyncDeviceServer.get_sensors
()Fetch a list of all sensors. AsyncDeviceServer.handle_inform
(connection, msg)Dispatch an inform message to the appropriate method. AsyncDeviceServer.handle_message
(…)Handle messages of all types from clients. AsyncDeviceServer.handle_reply
(connection, msg)Dispatch a reply message to the appropriate method. AsyncDeviceServer.handle_request
(connection, msg)Dispatch a request message to the appropriate method. AsyncDeviceServer.has_sensor
(sensor_name)Whether the sensor with specified name is known. AsyncDeviceServer.inform
(connection, msg)Send an inform message to a particular client. AsyncDeviceServer.join
([timeout])Rejoin the server thread. AsyncDeviceServer.mass_inform
(msg)Send an inform message to all clients. AsyncDeviceServer.next
()AsyncDeviceServer.on_client_connect
(**kwargs)Inform client of build state and version on connect. AsyncDeviceServer.on_client_disconnect
(…)Inform client it is about to be disconnected. AsyncDeviceServer.on_message
(client_conn, msg)Dummy implementation of on_message required by KATCPServer. AsyncDeviceServer.remove_sensor
(sensor)Remove a sensor from the device. AsyncDeviceServer.reply
(connection, reply, …)Send an asynchronous reply to an earlier request. AsyncDeviceServer.reply_inform
(connection, …)Send an inform as part of the reply to an earlier request. AsyncDeviceServer.request_client_list
(req, msg)Request the list of connected clients. AsyncDeviceServer.request_halt
(req, msg)Halt the device server. AsyncDeviceServer.request_help
(req, msg)Return help on the available requests. AsyncDeviceServer.request_log_level
(req, msg)Query or set the current logging level. AsyncDeviceServer.request_request_timeout_hint
(…)Return timeout hints for requests AsyncDeviceServer.request_restart
(req, msg)Restart the device server. AsyncDeviceServer.request_sensor_list
(req, msg)Request the list of sensors. AsyncDeviceServer.request_sensor_sampling
(…)Configure or query the way a sensor is sampled. AsyncDeviceServer.request_sensor_sampling_clear
(…)Set all sampling strategies for this client to none. AsyncDeviceServer.request_sensor_value
(req, msg)Request the value of a sensor or sensors. AsyncDeviceServer.request_version_list
(req, msg)Request the list of versions of roles and subcomponents. AsyncDeviceServer.request_watchdog
(req, msg)Check that the server is still alive. AsyncDeviceServer.running
()Whether the server is running. AsyncDeviceServer.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False AsyncDeviceServer.set_concurrency_options
([…])Set concurrency options for this device server. AsyncDeviceServer.set_ioloop
([ioloop])Set the tornado IOLoop to use. AsyncDeviceServer.set_restart_queue
(…)Set the restart queue. AsyncDeviceServer.setup_sensors
()Populate the dictionary of sensors. AsyncDeviceServer.start
([timeout])Start the server in a new thread. AsyncDeviceServer.stop
([timeout])Stop a running server (from another thread). AsyncDeviceServer.sync_with_ioloop
([timeout])Block for ioloop to complete a loop if called from another thread. AsyncDeviceServer.version
()Return a version string of the form type-major.minor. AsyncDeviceServer.wait_running
([timeout])Wait until the server is running
-
katcp.server.
BASE_REQUESTS
= frozenset(['sensor-sampling', 'help', 'new-command', 'raise-fail', 'client-list', 'log-level', 'raise-exception', 'version-list', 'sensor-value', 'sensor-sampling-clear', 'watchdog', 'sensor-list', 'restart', 'halt'])¶ List of basic KATCP requests that a minimal device server should implement
-
class
katcp.server.
ClientConnection
(server, conn_id)¶ Bases:
future.types.newobject.newobject
Encapsulates the connection between a single client and the server.
Methods
ClientConnection.disconnect
(reason)Disconnect this client connection for specified reason ClientConnection.inform
(msg)Send an inform message to a particular client. ClientConnection.mass_inform
(msg)Send an inform message to all clients. ClientConnection.next
()ClientConnection.on_client_disconnect_was_called
()Prevent multiple calls to on_client_disconnect handler. ClientConnection.reply
(reply, orig_req)Send an asynchronous reply to an earlier request. ClientConnection.reply_inform
(inform, orig_req)Send an inform as part of the reply to an earlier request. -
disconnect
(reason)¶ Disconnect this client connection for specified reason
-
inform
(msg)¶ Send an inform message to a particular client.
Should only be used for asynchronous informs. Informs that are part of the response to a request should use
reply_inform()
so that the message identifier from the original request can be attached to the inform.Parameters: msg : Message object
The inform message to send.
-
mass_inform
(msg)¶ Send an inform message to all clients.
Parameters: msg : Message object
The inform message to send.
-
on_client_disconnect_was_called
()¶ Prevent multiple calls to on_client_disconnect handler.
Call this when an on_client_disconnect handler has been called.
-
reply
(reply, orig_req)¶ Send an asynchronous reply to an earlier request.
Parameters: reply : Message object
The reply message to send.
orig_req : Message object
The request message being replied to. The reply message’s id is overridden with the id from orig_req before the reply is sent.
-
reply_inform
(inform, orig_req)¶ Send an inform as part of the reply to an earlier request.
Parameters: inform : Message object
The inform message to send.
orig_req : Message object
The request message being replied to. The inform message’s id is overridden with the id from orig_req before the inform is sent.
-
-
class
katcp.server.
ClientRequestConnection
(client_connection, req_msg)¶ Bases:
future.types.newobject.newobject
Encapsulates specific KATCP request and associated client connection.
Methods
ClientRequestConnection.inform
(*args)ClientRequestConnection.inform_after_reply
(*args)ClientRequestConnection.make_reply
(*args)ClientRequestConnection.next
()ClientRequestConnection.reply
(*args)ClientRequestConnection.reply_again
(*args)ClientRequestConnection.reply_with_message
(rep_msg)Send a pre-created reply message to the client connection. -
reply_with_message
(rep_msg)¶ Send a pre-created reply message to the client connection.
Will check that rep_msg.name matches the bound request.
-
-
class
katcp.server.
DeviceLogger
(device_server, root_logger='root', python_logger=None)¶ Bases:
future.types.newobject.newobject
Object for logging messages from a DeviceServer.
Log messages are logged at a particular level and under a particular name. Names use dotted notation to form a virtual hierarchy of loggers with the device.
Parameters: device_server : DeviceServerBase object
The device server this logger should use for sending out logs.
root_logger : str
The name of the root logger.
Methods
DeviceLogger.debug
(msg, *args, **kwargs)Log a debug message. DeviceLogger.error
(msg, *args, **kwargs)Log an error message. DeviceLogger.fatal
(msg, *args, **kwargs)Log a fatal error message. DeviceLogger.info
(msg, *args, **kwargs)Log an info message. DeviceLogger.level_from_name
(level_name)Return the level constant for a given name. DeviceLogger.level_name
([level])Return the name of the given level value. DeviceLogger.log
(level, msg, *args, **kwargs)Log a message and inform all clients. DeviceLogger.log_to_python
(logger, msg)Log a KATCP logging message to a Python logger. DeviceLogger.next
()DeviceLogger.set_log_level
(level)Set the logging level. DeviceLogger.set_log_level_by_name
(level_name)Set the logging level using a level name. DeviceLogger.trace
(msg, *args, **kwargs)Log a trace message. DeviceLogger.warn
(msg, *args, **kwargs)Log an warning message. -
debug
(msg, *args, **kwargs)¶ Log a debug message.
-
error
(msg, *args, **kwargs)¶ Log an error message.
-
fatal
(msg, *args, **kwargs)¶ Log a fatal error message.
-
info
(msg, *args, **kwargs)¶ Log an info message.
-
level_from_name
(level_name)¶ Return the level constant for a given name.
If the level_name is not known, raise a ValueError.
Parameters: level_name : str or bytes
The logging level name whose logging level constant to retrieve.
Returns: level : logging level constant
The logging level constant associated with the name.
-
level_name
(level=None)¶ Return the name of the given level value.
If level is None, return the name of the current level.
Parameters: level : logging level constant
The logging level constant whose name to retrieve.
Returns: level_name : str
The name of the logging level.
-
log
(level, msg, *args, **kwargs)¶ Log a message and inform all clients.
Parameters: level : logging level constant
The level to log the message at.
msg : str
The text format for the log message.
args : list of objects
Arguments to pass to log format string. Final message text is created using: msg % args.
kwargs : additional keyword parameters
Allowed keywords are ‘name’ and ‘timestamp’. The name is the name of the logger to log the message to. If not given the name defaults to the root logger. The timestamp is a float in seconds. If not given the timestamp defaults to the current time.
-
classmethod
log_to_python
(logger, msg)¶ Log a KATCP logging message to a Python logger.
Parameters: logger : logging.Logger object
The Python logger to log the given message to.
msg : Message object
The #log message to create a log entry from.
-
set_log_level
(level)¶ Set the logging level.
Parameters: level : logging level constant
The value to set the logging level to.
-
set_log_level_by_name
(level_name)¶ Set the logging level using a level name.
Parameters: level_name : str or bytes
The name of the logging level.
-
trace
(msg, *args, **kwargs)¶ Log a trace message.
-
warn
(msg, *args, **kwargs)¶ Log an warning message.
-
-
class
katcp.server.
DeviceServer
(*args, **kwargs)¶ Bases:
katcp.server.DeviceServerBase
Implements some standard messages on top of DeviceServerBase.
Inform messages handled are:
- version (sent on connect)
- build-state (sent on connect)
- log (via self.log.warn(…), etc)
- disconnect
- client-connected
Requests handled are:
- halt
- help
- log-level
- restart [1]
- client-list
- sensor-list
- sensor-sampling
- sensor-value
- watchdog
- version-list (only standard in KATCP v5 or later)
- request-timeout-hint (pre-standard only if protocol flags indicates
- timeout hints, supported for KATCP v5.1 or later)
- sensor-sampling-clear (non-standard)
[1] Restart relies on .set_restart_queue() being used to register a restart queue with the device. When the device needs to be restarted, it will be added to the restart queue. The queue should be a Python Queue.Queue object without a maximum size. Unhandled standard requests are:
- configure
- mode
Subclasses can define the tuple VERSION_INFO to set the interface name, major and minor version numbers. The BUILD_INFO tuple can be defined to give a string describing a particular interface instance and may have a fourth element containing additional version information (e.g. rc1).
Subclasses may manipulate the versions returned by the ?version-list command by editing .extra_versions which is a dictionary mapping role or component names to (version, build_state_or_serial_no) tuples. The build_state_or_serial_no may be None.
Subclasses must override the .setup_sensors() method. If they have no sensors to register, the method should just be a pass.
Methods
DeviceServer.add_sensor
(sensor)Add a sensor to the device. DeviceServer.build_state
()Return build state string of the form name-major.minor[(a|b|rc)n]. DeviceServer.clear_strategies
(client_conn[, …])Clear the sensor strategies of a client connection. DeviceServer.create_exception_reply_and_log
(…)DeviceServer.create_log_inform
(level_name, …)Create a katcp logging inform message. DeviceServer.get_sensor
(sensor_name)Fetch the sensor with the given name. DeviceServer.get_sensors
()Fetch a list of all sensors. DeviceServer.handle_inform
(connection, msg)Dispatch an inform message to the appropriate method. DeviceServer.handle_message
(client_conn, msg)Handle messages of all types from clients. DeviceServer.handle_reply
(connection, msg)Dispatch a reply message to the appropriate method. DeviceServer.handle_request
(connection, msg)Dispatch a request message to the appropriate method. DeviceServer.has_sensor
(sensor_name)Whether the sensor with specified name is known. DeviceServer.inform
(connection, msg)Send an inform message to a particular client. DeviceServer.join
([timeout])Rejoin the server thread. DeviceServer.mass_inform
(msg)Send an inform message to all clients. DeviceServer.next
()DeviceServer.on_client_connect
(**kwargs)Inform client of build state and version on connect. DeviceServer.on_client_disconnect
(…)Inform client it is about to be disconnected. DeviceServer.on_message
(client_conn, msg)Dummy implementation of on_message required by KATCPServer. DeviceServer.remove_sensor
(sensor)Remove a sensor from the device. DeviceServer.reply
(connection, reply, orig_req)Send an asynchronous reply to an earlier request. DeviceServer.reply_inform
(connection, …)Send an inform as part of the reply to an earlier request. DeviceServer.request_client_list
(req, msg)Request the list of connected clients. DeviceServer.request_halt
(req, msg)Halt the device server. DeviceServer.request_help
(req, msg)Return help on the available requests. DeviceServer.request_log_level
(req, msg)Query or set the current logging level. DeviceServer.request_request_timeout_hint
(…)Return timeout hints for requests DeviceServer.request_restart
(req, msg)Restart the device server. DeviceServer.request_sensor_list
(req, msg)Request the list of sensors. DeviceServer.request_sensor_sampling
(req, msg)Configure or query the way a sensor is sampled. DeviceServer.request_sensor_sampling_clear
(…)Set all sampling strategies for this client to none. DeviceServer.request_sensor_value
(req, msg)Request the value of a sensor or sensors. DeviceServer.request_version_list
(req, msg)Request the list of versions of roles and subcomponents. DeviceServer.request_watchdog
(req, msg)Check that the server is still alive. DeviceServer.running
()Whether the server is running. DeviceServer.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False DeviceServer.set_concurrency_options
([…])Set concurrency options for this device server. DeviceServer.set_ioloop
([ioloop])Set the tornado IOLoop to use. DeviceServer.set_restart_queue
(restart_queue)Set the restart queue. DeviceServer.setup_sensors
()Populate the dictionary of sensors. DeviceServer.start
([timeout])Start the server in a new thread. DeviceServer.stop
([timeout])Stop a running server (from another thread). DeviceServer.sync_with_ioloop
([timeout])Block for ioloop to complete a loop if called from another thread. DeviceServer.version
()Return a version string of the form type-major.minor. DeviceServer.wait_running
([timeout])Wait until the server is running -
add_sensor
(sensor)¶ Add a sensor to the device.
Usually called inside .setup_sensors() but may be called from elsewhere.
Parameters: sensor : Sensor object
The sensor object to register with the device server.
-
build_state
()¶ Return build state string of the form name-major.minor[(a|b|rc)n].
-
clear_strategies
(client_conn, remove_client=False)¶ Clear the sensor strategies of a client connection.
Parameters: client_connection : ClientConnection instance
The connection that should have its sampling strategies cleared
remove_client : bool, optional
Remove the client connection from the strategies data-structure. Useful for clients that disconnect.
-
get_sensor
(sensor_name)¶ Fetch the sensor with the given name.
Parameters: sensor_name : str
Name of the sensor to retrieve.
Returns: sensor : Sensor object
The sensor with the given name.
-
get_sensors
()¶ Fetch a list of all sensors.
Returns: sensors : list of Sensor objects
The list of sensors registered with the device server.
-
has_sensor
(sensor_name)¶ Whether the sensor with specified name is known.
-
on_client_connect
(**kwargs)¶ Inform client of build state and version on connect.
Parameters: client_conn : ClientConnection object
The client connection that has been successfully established.
Returns: Future that resolves when the device is ready to accept messages. :
-
on_client_disconnect
(client_conn, msg, connection_valid)¶ Inform client it is about to be disconnected.
Parameters: client_conn : ClientConnection object
The client connection being disconnected.
msg : str
Reason client is being disconnected.
connection_valid : bool
True if connection is still open for sending, False otherwise.
Returns: Future that resolves when the client connection can be closed. :
-
remove_sensor
(sensor)¶ Remove a sensor from the device.
Also deregisters all clients observing the sensor.
Parameters: sensor : Sensor object or name string
The sensor to remove from the device server.
-
request_client_list
(req, msg)¶ Request the list of connected clients.
The list of clients is sent as a sequence of #client-list informs.
Informs: addr : str
The address of the client as host:port with host in dotted quad notation. If the address of the client could not be determined (because, for example, the client disconnected suddenly) then a unique string representing the client is sent instead.
Returns: success : {‘ok’, ‘fail’}
Whether sending the client list succeeded.
informs : int
Number of #client-list inform messages sent.
Examples
?client-list #client-list 127.0.0.1:53600 !client-list ok 1
-
request_halt
(req, msg)¶ Halt the device server.
Returns: success : {‘ok’, ‘fail’}
Whether scheduling the halt succeeded.
Examples
?halt !halt ok
-
request_help
(req, msg)¶ Return help on the available requests.
Return a description of the available requests using a sequence of #help informs.
Parameters: request : str, optional
The name of the request to return help for (the default is to return help for all requests).
Informs: request : str
The name of a request.
description : str
Documentation for the named request.
Returns: success : {‘ok’, ‘fail’}
Whether sending the help succeeded.
informs : int
Number of #help inform messages sent.
Examples
?help #help halt ...description... #help help ...description... ... !help ok 5 ?help halt #help halt ...description... !help ok 1
-
request_log_level
(req, msg)¶ Query or set the current logging level.
Parameters: level : {‘all’, ‘trace’, ‘debug’, ‘info’, ‘warn’, ‘error’, ‘fatal’, ‘off’}, optional
Name of the logging level to set the device server to (the default is to leave the log level unchanged).
Returns: success : {‘ok’, ‘fail’}
Whether the request succeeded.
level : {‘all’, ‘trace’, ‘debug’, ‘info’, ‘warn’, ‘error’, ‘fatal’, ‘off’}
The log level after processing the request.
Examples
?log-level !log-level ok warn ?log-level info !log-level ok info
-
request_request_timeout_hint
(req, msg)¶ Return timeout hints for requests
KATCP requests should generally take less than 5s to complete, but some requests are unavoidably slow. This results in spurious client timeout errors. This request provides timeout hints that clients can use to select suitable request timeouts.
Parameters: request : str, optional
The name of the request to return a timeout hint for (the default is to return hints for all requests that have timeout hints). Returns one inform per request. Must be an existing request if specified.
Informs: request : str
The name of the request.
suggested_timeout : float
Suggested request timeout in seconds for the request. If suggested_timeout is zero (0), no timeout hint is available.
Returns: success : {‘ok’, ‘fail’}
Whether sending the help succeeded.
informs : int
Number of #request-timeout-hint inform messages sent.
Notes
?request-timeout-hint without a parameter will only return informs for requests that have specific timeout hints, so it will most probably be a subset of all the requests, or even no informs at all.
Examples
?request-timeout-hint #request-timeout-hint halt 5 #request-timeout-hint very-slow-request 500 ... !request-timeout-hint ok 5 ?request-timeout-hint moderately-slow-request #request-timeout-hint moderately-slow-request 20 !request-timeout-hint ok 1
-
request_restart
(req, msg)¶ Restart the device server.
Returns: success : {‘ok’, ‘fail’}
Whether scheduling the restart succeeded.
Examples
?restart !restart ok
-
request_sensor_list
(req, msg)¶ Request the list of sensors.
The list of sensors is sent as a sequence of #sensor-list informs.
Parameters: name : str, optional
Name of the sensor to list (the default is to list all sensors). If name starts and ends with ‘/’ it is treated as a regular expression and all sensors whose names contain the regular expression are returned.
Informs: name : str
The name of the sensor being described.
description : str
Description of the named sensor.
units : str
Units for the value of the named sensor.
type : str
Type of the named sensor.
params : list of str, optional
Additional sensor parameters (type dependent). For integer and float sensors the additional parameters are the minimum and maximum sensor value. For discrete sensors the additional parameters are the allowed values. For all other types no additional parameters are sent.
Returns: success : {‘ok’, ‘fail’}
Whether sending the sensor list succeeded.
informs : int
Number of #sensor-list inform messages sent.
Examples
?sensor-list #sensor-list psu.voltage PSU\_voltage. V float 0.0 5.0 #sensor-list cpu.status CPU\_status. \@ discrete on off error ... !sensor-list ok 5 ?sensor-list cpu.power.on #sensor-list cpu.power.on Whether\_CPU\_hase\_power. \@ boolean !sensor-list ok 1 ?sensor-list /voltage/ #sensor-list psu.voltage PSU\_voltage. V float 0.0 5.0 #sensor-list cpu.voltage CPU\_voltage. V float 0.0 3.0 !sensor-list ok 2
-
request_sensor_sampling
(req, msg)¶ Configure or query the way a sensor is sampled.
Sampled values are reported asynchronously using the #sensor-status message.
Parameters: names : str
One or more names of sensors whose sampling strategy will be queried or configured. If specifying multiple sensors, these must be provided as a comma-separated list. A query can only be done on a single sensor. However, configuration can be done on many sensors with a single request, as long as they all use the same strategy. Note: prior to KATCP v5.1 only a single sensor could be configured. Multiple sensors are only allowed if the device server sets the protocol version to KATCP v5.1 or higher and enables the BULK_SET_SENSOR_SAMPLING flag in its PROTOCOL_INFO class attribute.
strategy : {‘none’, ‘auto’, ‘event’, ‘differential’, ‘differential-rate’,
‘period’, ‘event-rate’}, optional
Type of strategy to use to report the sensor value. The differential strategy types may only be used with integer or float sensors. If this parameter is supplied, it sets the new strategy.
params : list of str, optional
Additional strategy parameters (dependent on the strategy type). For the differential strategy, the parameter is an integer or float giving the amount by which the sensor value may change before an updated value is sent. For the period strategy, the parameter is the sampling period in float seconds. The event strategy has no parameters. Note that this has changed from KATCPv4. For the event-rate strategy, a minimum period between updates and a maximum period between updates (both in float seconds) must be given. If the event occurs more than once within the minimum period, only one update will occur. Whether or not the event occurs, the sensor value will be updated at least once per maximum period. For the differential-rate strategy there are 3 parameters. The first is the same as the differential strategy parameter. The second and third are the minimum and maximum periods, respectively, as with the event-rate strategy.
Informs: timestamp : float
Timestamp of the sensor reading in seconds since the Unix epoch, or milliseconds for katcp versions <= 4.
count : {1}
Number of sensors described in this #sensor-status inform. Will always be one. It exists to keep this inform compatible with #sensor-value.
name : str
Name of the sensor whose value is being reported.
value : object
Value of the named sensor. Type depends on the type of the sensor.
Returns: success : {‘ok’, ‘fail’}
Whether the sensor-sampling request succeeded.
names : str
Name(s) of the sensor queried or configured. If multiple sensors, this will be a comma-separated list.
strategy : {‘none’, ‘auto’, ‘event’, ‘differential’, ‘differential-rate’,
‘period’, ‘event-rate’}.
Name of the new or current sampling strategy for the sensor(s).
params : list of str
Additional strategy parameters (see description under Parameters).
Examples :
——– :
:: :
?sensor-sampling cpu.power.on !sensor-sampling ok cpu.power.on none
?sensor-sampling cpu.power.on period 0.5 #sensor-status 1244631611.415231 1 cpu.power.on nominal 1 !sensor-sampling ok cpu.power.on period 0.5
if BULK_SET_SENSOR_SAMPLING is enabled then:
?sensor-sampling cpu.power.on,fan.speed !sensor-sampling fail Cannot_query_multiple_sensors
?sensor-sampling cpu.power.on,fan.speed period 0.5 #sensor-status 1244631611.415231 1 cpu.power.on nominal 1 #sensor-status 1244631611.415200 1 fan.speed nominal 10.0 !sensor-sampling ok cpu.power.on,fan.speed period 0.5
-
request_sensor_sampling_clear
(req, msg)¶ Set all sampling strategies for this client to none.
Returns: success : {‘ok’, ‘fail’}
Whether sending the list of devices succeeded.
Examples
?sensor-sampling-clear !sensor-sampling-clear ok
-
request_sensor_value
(req, msg)¶ Request the value of a sensor or sensors.
A list of sensor values as a sequence of #sensor-value informs.
Parameters: name : str, optional
Name of the sensor to poll (the default is to send values for all sensors). If name starts and ends with ‘/’ it is treated as a regular expression and all sensors whose names contain the regular expression are returned.
Informs: timestamp : float
Timestamp of the sensor reading in seconds since the Unix epoch, or milliseconds for katcp versions <= 4.
count : {1}
Number of sensors described in this #sensor-value inform. Will always be one. It exists to keep this inform compatible with #sensor-status.
name : str
Name of the sensor whose value is being reported.
value : object
Value of the named sensor. Type depends on the type of the sensor.
Returns: success : {‘ok’, ‘fail’}
Whether sending the list of values succeeded.
informs : int
Number of #sensor-value inform messages sent.
Examples
?sensor-value #sensor-value 1244631611.415231 1 psu.voltage nominal 4.5 #sensor-value 1244631611.415200 1 cpu.status nominal off ... !sensor-value ok 5 ?sensor-value cpu.power.on #sensor-value 1244631611.415231 1 cpu.power.on nominal 0 !sensor-value ok 1
-
request_version_list
(req, msg)¶ Request the list of versions of roles and subcomponents.
Informs: name : str
Name of the role or component.
version : str
A string identifying the version of the component. Individual components may define the structure of this argument as they choose. In the absence of other information clients should treat it as an opaque string.
build_state_or_serial_number : str
A unique identifier for a particular instance of a component. This should change whenever the component is replaced or updated.
Returns: success : {‘ok’, ‘fail’}
Whether sending the version list succeeded.
informs : int
Number of #version-list inform messages sent.
Examples
?version-list #version-list katcp-protocol 5.0-MI #version-list katcp-library katcp-python-0.4 katcp-python-0.4.1-py2 #version-list katcp-device foodevice-1.0 foodevice-1.0.0rc1 !version-list ok 3
-
request_watchdog
(req, msg)¶ Check that the server is still alive.
Returns: success : {‘ok’} Examples
?watchdog !watchdog ok
-
set_restart_queue
(restart_queue)¶ Set the restart queue.
When the device server should be restarted, it will be added to the queue.
Parameters: restart_queue : Queue.Queue object
The queue to add the device server to when it should be restarted.
-
setup_sensors
()¶ Populate the dictionary of sensors.
Unimplemented by default – subclasses should add their sensors here or pass if there are no sensors.
Examples
>>> class MyDevice(DeviceServer): ... def setup_sensors(self): ... self.add_sensor(Sensor(...)) ... self.add_sensor(Sensor(...)) ...
-
version
()¶ Return a version string of the form type-major.minor.
-
class
katcp.server.
DeviceServerBase
(host, port, tb_limit=20, logger=<logging.Logger object>)¶ Bases:
future.types.newobject.newobject
Base class for device servers.
Subclasses should add .request_* methods for dealing with request messages. These methods each take the client request connection and msg objects as arguments and should return the reply message or raise an exception as a result.
Subclasses can also add .inform_* and reply_* methods to handle those types of messages.
Should a subclass need to generate inform messages it should do so using either the .inform() or .mass_inform() methods.
Finally, this class should probably not be subclassed directly but rather via subclassing DeviceServer itself which implements common .request_* methods.
Parameters: host : str
Host to listen on.
port : int
Port to listen on.
tb_limit : int, optional
Maximum number of stack frames to send in error tracebacks.
logger : logging.Logger object, optional
Logger to log messages to.
Methods
DeviceServerBase.create_exception_reply_and_log
(…)DeviceServerBase.create_log_inform
(…[, …])Create a katcp logging inform message. DeviceServerBase.handle_inform
(connection, msg)Dispatch an inform message to the appropriate method. DeviceServerBase.handle_message
(client_conn, msg)Handle messages of all types from clients. DeviceServerBase.handle_reply
(connection, msg)Dispatch a reply message to the appropriate method. DeviceServerBase.handle_request
(connection, msg)Dispatch a request message to the appropriate method. DeviceServerBase.inform
(connection, msg)Send an inform message to a particular client. DeviceServerBase.join
([timeout])Rejoin the server thread. DeviceServerBase.mass_inform
(msg)Send an inform message to all clients. DeviceServerBase.next
()DeviceServerBase.on_client_connect
(**kwargs)Called after client connection is established. DeviceServerBase.on_client_disconnect
(**kwargs)Called before a client connection is closed. DeviceServerBase.on_message
(client_conn, msg)Dummy implementation of on_message required by KATCPServer. DeviceServerBase.reply
(connection, reply, …)Send an asynchronous reply to an earlier request. DeviceServerBase.reply_inform
(connection, …)Send an inform as part of the reply to an earlier request. DeviceServerBase.running
()Whether the server is running. DeviceServerBase.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False DeviceServerBase.set_concurrency_options
([…])Set concurrency options for this device server. DeviceServerBase.set_ioloop
([ioloop])Set the tornado IOLoop to use. DeviceServerBase.start
([timeout])Start the server in a new thread. DeviceServerBase.stop
([timeout])Stop a running server (from another thread). DeviceServerBase.sync_with_ioloop
([timeout])Block for ioloop to complete a loop if called from another thread. DeviceServerBase.wait_running
([timeout])Wait until the server is running -
create_log_inform
(level_name, msg, name, timestamp=None)¶ Create a katcp logging inform message.
Usually this will be called from inside a DeviceLogger object, but it is also used by the methods in this class when errors need to be reported to the client.
-
handle_inform
(connection, msg)¶ Dispatch an inform message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The inform message to process.
-
handle_message
(client_conn, msg)¶ Handle messages of all types from clients.
Parameters: client_conn : ClientConnection object
The client connection the message was from.
msg : Message object
The message to process.
-
handle_reply
(connection, msg)¶ Dispatch a reply message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The reply message to process.
-
handle_request
(connection, msg)¶ Dispatch a request message to the appropriate method.
Parameters: connection : ClientConnection object
The client connection the message was from.
msg : Message object
The request message to process.
Returns: done_future : Future or None
Returns Future for async request handlers that will resolve when done, or None for sync request handlers once they have completed.
-
inform
(connection, msg)¶ Send an inform message to a particular client.
Should only be used for asynchronous informs. Informs that are part of the response to a request should use
reply_inform()
so that the message identifier from the original request can be attached to the inform.Parameters: connection : ClientConnection object
The client to send the message to.
msg : Message object
The inform message to send.
-
join
(timeout=None)¶ Rejoin the server thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for the thread to finish.
-
mass_inform
(msg)¶ Send an inform message to all clients.
Parameters: msg : Message object
The inform message to send.
-
on_client_connect
(**kwargs)¶ Called after client connection is established.
Subclasses should override if they wish to send clients message or perform house-keeping at this point.
Parameters: conn : ClientConnection object
The client connection that has been successfully established.
Returns: Future that resolves when the device is ready to accept messages. :
-
on_client_disconnect
(**kwargs)¶ Called before a client connection is closed.
Subclasses should override if they wish to send clients message or perform house-keeping at this point. The server cannot guarantee this will be called (for example, the client might drop the connection). The message parameter contains the reason for the disconnection.
Parameters: conn : ClientConnection object
Client connection being disconnected.
msg : str
Reason client is being disconnected.
connection_valid : boolean
True if connection is still open for sending, False otherwise.
Returns: Future that resolves when the client connection can be closed. :
-
on_message
(client_conn, msg)¶ Dummy implementation of on_message required by KATCPServer.
Will be replaced by a handler with the appropriate concurrency semantics when set_concurrency_options is called (defaults are set in __init__()).
-
reply
(connection, reply, orig_req)¶ Send an asynchronous reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the reply to.
reply : Message object
The reply message to send.
orig_req : Message object
The request message being replied to. The reply message’s id is overridden with the id from orig_req before the reply is sent.
-
reply_inform
(connection, inform, orig_req)¶ Send an inform as part of the reply to an earlier request.
Parameters: connection : ClientConnection object
The client to send the inform to.
inform : Message object
The inform message to send.
orig_req : Message object
The request message being replied to. The inform message’s id is overridden with the id from orig_req before the inform is sent.
-
running
()¶ Whether the server is running.
-
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
set_concurrency_options
(thread_safe=True, handler_thread=True)¶ Set concurrency options for this device server. Must be called before
start()
.Parameters: thread_safe : bool
If True, make the server public methods thread safe. Incurs performance overhead.
handler_thread : bool
Can only be set if thread_safe is True. Handle all requests (even from different clients) in a separate, single, request-handling thread. Blocking request handlers will prevent the server from handling new requests from any client, but sensor strategies should still function. This more or less mimics the behaviour of a server in library versions before 0.6.0.
-
set_ioloop
(ioloop=None)¶ Set the tornado IOLoop to use.
Sets the tornado.ioloop.IOLoop instance to use, defaulting to IOLoop.current(). If set_ioloop() is never called the IOLoop is started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called.
-
start
(timeout=None)¶ Start the server in a new thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for server thread to start.
-
stop
(timeout=1.0)¶ Stop a running server (from another thread).
Parameters: timeout : float, optional
Seconds to wait for server to have started.
Returns: stopped : thread-safe Future
Resolves when the server is stopped
-
sync_with_ioloop
(timeout=None)¶ Block for ioloop to complete a loop if called from another thread.
Returns a future if called from inside the ioloop.
Raises concurrent.futures.TimeoutError if timed out while blocking.
-
wait_running
(timeout=None)¶ Wait until the server is running
-
-
class
katcp.server.
KATCPServer
(device, host, port, tb_limit=20, logger=<logging.Logger object>)¶ Bases:
future.types.newobject.newobject
Tornado IO backend for a KATCP Device.
Listens for connections on a server socket, reads KATCP messages off the wire and passes them on to a DeviceServer-like class.
All class CONSTANT attributes can be changed until start() is called.
Methods
KATCPServer.call_from_thread
(fn)Allow thread-safe calls to ioloop functions. KATCPServer.client_connection_factory
Factory that produces a ClientConnection compatible instance. KATCPServer.flush_on_close
(stream)Flush tornado iostream write buffer and prevent further writes. KATCPServer.get_address
(stream)Text representation of the network address of a connection stream. KATCPServer.in_ioloop_thread
()Return True if called in the IOLoop thread of this server. KATCPServer.join
([timeout])Rejoin the server thread. KATCPServer.mass_send_message
(msg)Send a message to all connected clients. KATCPServer.mass_send_message_from_thread
(msg)Thread-safe version of send_message() returning a Future instance. KATCPServer.next
()KATCPServer.running
()Whether the handler thread is running. KATCPServer.send_message
(stream, msg)Send an arbitrary message to a particular client. KATCPServer.send_message_from_thread
(stream, msg)Thread-safe version of send_message() returning a Future instance. KATCPServer.setDaemon
(daemonic)Set daemonic state of the managed ioloop thread to True / False KATCPServer.set_ioloop
([ioloop])Set the tornado IOLoop to use. KATCPServer.start
([timeout])Install the server on its IOLoop, optionally starting the IOLoop. KATCPServer.stop
([timeout])Stop a running server (from another thread). KATCPServer.wait_running
([timeout])Wait until the handler thread is running. -
DISCONNECT_TIMEOUT
= 1¶ How long to wait for the device on_client_disconnect() to complete.
Note that this will only work if the device on_client_disconnect() method is non-blocking (i.e. returns a future immediately). Otherwise the ioloop will be blocked and unable to apply the timeout.
-
MAX_MSG_SIZE
= 2097152¶ Maximum message size that can be received in bytes.
If more than MAX_MSG_SIZE bytes are read from the client without encountering a message terminator (i.e. newline), the connection is closed.
-
MAX_WRITE_BUFFER_SIZE
= 4194304¶ Maximum outstanding bytes to be buffered by the server process.
If more than MAX_WRITE_BUFFER_SIZE bytes are outstanding, the client connection is closed. Note that the OS also buffers socket writes, so more than MAX_WRITE_BUFFER_SIZE bytes may be untransmitted in total.
-
bind_address
¶ The (host, port) where the server is listening for connections.
-
call_from_thread
(fn)¶ Allow thread-safe calls to ioloop functions.
Uses add_callback if not in the IOLoop thread, otherwise calls directly. Returns an already resolved tornado.concurrent.Future if in ioloop, otherwise a concurrent.Future. Logs unhandled exceptions. Resolves with an exception if one occurred.
-
client_connection_factory
¶ Factory that produces a ClientConnection compatible instance.
signature: client_connection_factory(server, conn_id)
Should be set before calling start().
Methods
ClientConnection.disconnect
(reason)Disconnect this client connection for specified reason ClientConnection.inform
(msg)Send an inform message to a particular client. ClientConnection.mass_inform
(msg)Send an inform message to all clients. ClientConnection.next
()ClientConnection.on_client_disconnect_was_called
()Prevent multiple calls to on_client_disconnect handler. ClientConnection.reply
(reply, orig_req)Send an asynchronous reply to an earlier request. ClientConnection.reply_inform
(inform, orig_req)Send an inform as part of the reply to an earlier request. alias of
ClientConnection
-
flush_on_close
(stream)¶ Flush tornado iostream write buffer and prevent further writes.
Returns a future that resolves when the stream is flushed.
-
get_address
(stream)¶ Text representation of the network address of a connection stream.
Notes
This method is thread-safe
-
in_ioloop_thread
()¶ Return True if called in the IOLoop thread of this server.
-
ioloop
= None¶ The Tornado IOloop to use, set by self.set_ioloop()
-
join
(timeout=None)¶ Rejoin the server thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for the thread to finish.
Notes
If the ioloop is not managed, this function will block until the server port is closed, meaning a new server can be started on the same port.
-
mass_send_message
(msg)¶ Send a message to all connected clients.
Notes
This method can only be called in the IOLoop thread.
-
mass_send_message_from_thread
(msg)¶ Thread-safe version of send_message() returning a Future instance.
See return value and notes for send_message_from_thread().
-
running
()¶ Whether the handler thread is running.
-
send_message
(stream, msg)¶ Send an arbitrary message to a particular client.
Parameters: stream :
tornado.iostream.IOStream
objectThe stream to send the message to.
msg : Message object
The message to send.
Notes
This method can only be called in the IOLoop thread.
Failed sends disconnect the client connection and calls the device on_client_disconnect() method. They do not raise exceptions, but they are logged. Sends also fail if more than self.MAX_WRITE_BUFFER_SIZE bytes are queued for sending, implying that client is falling behind.
-
send_message_from_thread
(stream, msg)¶ Thread-safe version of send_message() returning a Future instance.
Returns: A Future that will resolve without raising an exception as soon as :
the call to send_message() completes. This does not guarantee that the :
message has been delivered yet. If the call to send_message() failed, :
the exception will be logged, and the future will resolve with the :
exception raised. Since a failed call to send_message() will result :
in the connection being closed, no real error handling apart from :
logging will be possible. :
Notes
This method is thread-safe. If called from within the ioloop, send_message is called directly and a resolved tornado.concurrent.Future is returned, otherwise a callback is submitted to the ioloop that will resolve a thread-safe concurrent.futures.Future instance.
-
setDaemon
(daemonic)¶ Set daemonic state of the managed ioloop thread to True / False
Calling this method for a non-managed ioloop has no effect. Must be called before start(), or it will also have no effect
-
set_ioloop
(ioloop=None)¶ Set the tornado IOLoop to use.
Sets the tornado.ioloop.IOLoop instance to use, defaulting to IOLoop.current(). If set_ioloop() is never called the IOLoop is started in a new thread, and will be stopped if self.stop() is called.
Notes
Must be called before start() is called.
-
start
(timeout=None)¶ Install the server on its IOLoop, optionally starting the IOLoop.
Parameters: timeout : float or None, optional
Time in seconds to wait for server thread to start.
-
stop
(timeout=1.0)¶ Stop a running server (from another thread).
Parameters: timeout : float or None, optional
Seconds to wait for server to have started.
Returns: stopped : thread-safe Future
Resolves when the server is stopped
-
wait_running
(timeout=None)¶ Wait until the handler thread is running.
-
-
class
katcp.server.
MessageHandlerThread
(handler, log_inform_formatter, logger=<logging.Logger object>)¶ Bases:
future.types.newobject.newobject
Provides backwards compatibility for server expecting its own thread.
Methods
MessageHandlerThread.isAlive
()MessageHandlerThread.join
([timeout])Rejoin the handler thread. MessageHandlerThread.next
()MessageHandlerThread.on_message
(client_conn, msg)Handle message. MessageHandlerThread.run
()MessageHandlerThread.running
()Whether the handler thread is running. MessageHandlerThread.set_ioloop
(ioloop)MessageHandlerThread.start
([timeout])MessageHandlerThread.stop
([timeout])Stop the handler thread (from another thread). MessageHandlerThread.wait_running
([timeout])Wait until the handler thread is running. -
join
(timeout=None)¶ Rejoin the handler thread.
Parameters: timeout : float or None, optional
Time in seconds to wait for the thread to finish.
-
on_message
(client_conn, msg)¶ Handle message.
Returns: ready : Future
A future that will resolve once we’re ready, else None.
Notes
on_message should not be called again until ready has resolved.
-
running
()¶ Whether the handler thread is running.
-
stop
(timeout=1.0)¶ Stop the handler thread (from another thread).
Parameters: timeout : float, optional
Seconds to wait for server to have started.
-
wait_running
(timeout=None)¶ Wait until the handler thread is running.
-
-
class
katcp.server.
ThreadsafeClientConnection
(server, conn_id)¶ Bases:
katcp.server.ClientConnection
Make ClientConnection compatible with messages sent from other threads.
Methods
ThreadsafeClientConnection.disconnect
(reason)Disconnect this client connection for specified reason ThreadsafeClientConnection.inform
(msg)Send an inform message to a particular client. ThreadsafeClientConnection.mass_inform
(msg)Send an inform message to all clients. ThreadsafeClientConnection.next
()ThreadsafeClientConnection.on_client_disconnect_was_called
()Prevent multiple calls to on_client_disconnect handler. ThreadsafeClientConnection.reply
(reply, orig_req)Send an asynchronous reply to an earlier request. ThreadsafeClientConnection.reply_inform
(…)Send an inform as part of the reply to an earlier request.
-
katcp.server.
construct_name_filter
(pattern)¶ Return a function for filtering sensor names based on a pattern.
Parameters: pattern : None or str
If None, the returned function matches all names. If pattern starts and ends with ‘/’ the text between the slashes is used as a regular expression to search the names. Otherwise the pattern must match the name of the sensor exactly.
Returns: exact : bool
Return True if pattern is expected to match exactly. Used to determine whether having no matching sensors constitutes an error.
filter_func : f(str) -> bool
Function for determining whether a name matches the pattern.
-
katcp.server.
return_future
(fn)¶ Decorator that turns a synchronous function into one returning a future.
This should only be applied to non-blocking functions. Will do set_result() with the return value, or set_exc_info() if an exception is raised.
Tutorial¶
Installing the Python Katcp Library¶
Stable release¶
To install katcp, run this command in your terminal:
$ pip install katcp
This is the preferred method to install katcp, as it will always install the most recent stable release.
If you don’t have pip installed, this Python installation guide can guide you through the process.
Alternatively,
$ easy_install katcp
Note: This requires the setuptools Python package to be installed.
From sources¶
The sources for katcp can be downloaded from the Github repo.
You can either clone the public repository:
$ git clone https://github.com/ska-sa/katcp-python/
Or download the tarball:
$ curl -OJL https://github.com/ska-sa/katcp-python/tarball/master
Once you have a copy of the source, you can install it with:
$ python setup.py install
Usage¶
Using the Blocking Client¶
The blocking client is the most straight-forward way of querying a KATCP device. It is used as follows:
from katcp import BlockingClient, Message
device_host = "www.example.com"
device_port = 5000
client = BlockingClient(device_host, device_port)
client.start()
client.wait_protocol() # Optional
reply, informs = client.blocking_request(
Message.request("help"))
print reply
for msg in informs:
print msg
client.stop()
client.join()
After creating the BlockingClient
instance, the
start()
method is called to launch the client thread. The
wait_protocol()
method waits until katcp version information has been
received from the server, allowing the KATCP version spoken by the server to be
known; server protocol information is stores in client.protocol_flags. Once you
have finished with the client, stop()
can be called to request that the
thread shutdown. Finally, join()
is used to wait for the client thread to
finish.
While the client is active the blocking_request()
method can be used to send messages to
the KATCP server and wait for replies. If a reply is not received within the
allowed time, a RuntimeError
is raised.
If a reply is received blocking_request()
returns two values. The first is the
Message
containing the reply. The second is a list of
messages containing any KATCP informs associated with the reply.
Using the Callback Client¶
For situations where one wants to communicate with a server
but doesn’t want to wait for a reply, the
CallbackClient
is provided:
from katcp import CallbackClient, Message
device_host = "www.example.com"
device_port = 5000
def reply_cb(msg):
print "Reply:", msg
def inform_cb(msg):
print "Inform:", msg
client = CallbackClient(device_host, device_port)
client.start()
reply, informs = client.callback_request(
Message.request("help"),
reply_cb=reply_cb,
inform_cb=inform_cb,
)
client.stop()
client.join()
Note that the reply_cb()
and inform_cb()
callback functions are both
called inside the client’s event-loop thread so should not perform any
operations that block. If needed, pass the data out from the callback
function to another thread using a Queue.Queue
or similar
structure.
Writing your own Client¶
If neither the BlockingClient
nor
the CallbackClient
provide the
functionality you need then you can sub-class
DeviceClient
which is the base class
from which both are derived.
DeviceClient
has two methods for sending messages:
request()
for sending requestMessages
send_message
for sending arbitraryMessages
Internally request
calls
send_message
to pass messages to the
server.
Note
The send_message()
method does not
return an error code or raise an exception if sending the message
fails. Since the underlying protocol is entirely asynchronous, the only
means to check that a request was successful is receive a reply message. One
can check that the client is connected before sending a message using
is_connected()
.
When the DeviceClient
thread receives a completed message,
handle_message()
is called. The default handle_message()
implementation calls one of handle_reply()
, handle_inform()
or handle_request()
depending on the type of message received.
Note
Sending requests to clients is discouraged. The handle_request()
is provided mostly for completeness and to deal with unforseen
circumstances.
Each of handle_reply()
, handle_inform()
and handle_request()
dispatches messages to methods based on the message name. For example,
a reply message named foo
will be dispatched to reply_foo()
.
Similarly an inform message named bar
will be dispatched to
inform_bar()
. If no corresponding method is found then one of
unhandled_reply()
, unhandled_inform()
or unhandled_request()
is called.
Your own client may hook into this dispatch tree at any point by implementing or overriding the appropriate methods.
An example of a simple client that only handles replies to help
messages is presented below:
from katcp import DeviceClient, Message
import time
device_host = "www.example.com"
device_port = 5000
class MyClient(DeviceClient):
def reply_help(self, msg):
"""Print out help replies."""
print msg.name, msg.arguments
def inform_help(self, msg):
"""Print out help inform messages."""
meth, desc = msg.arguments[:2]
print "---------", meth, "---------"
print
print desc
print "----------------------------"
def unhandled_reply(self, msg):
"""Print out unhandled replies."""
print "Unhandled reply", msg.name
def unhandled_inform(self, msg):
"Print out unhandled informs."""
print "Unhandled inform", msg.name
client = MyClient(device_host, device_port)
client.start()
client.request(Message.request("help"))
client.request(Message.request("watchdog"))
time.sleep(0.5)
client.stop()
client.join()
Client handler functions can use the unpack_message()
decorator from kattypes module to unpack
messages into function arguments in the same way the request()
decorator is used in the server example below, except
that the req parameter is omitted.
Using the high-level client API¶
The high level client API inspects a KATCP device server and presents requests as method calls and sensors as objects.
A high level client for the example server presented in the following section:
import tornado
from tornado.ioloop import IOLoop
from katcp import resource_client
ioloop = IOLoop.current()
client = resource_client.KATCPClientResource(dict(
name='demo-client',
address=('localhost', 5000),
controlled=True))
@tornado.gen.coroutine
def demo():
# Wait until the client has finished inspecting the device
yield client.until_synced()
help_response = yield client.req.help()
print "device help:\n ", help_response
add_response = yield client.req.add(3, 6)
print "3 + 6 response:\n", add_response
# By not yielding we are not waiting for the response
pick_response_future = client.req.pick_fruit()
# Instead we wait for the fruit.result sensor status to change to
# nominal. Before we can wait on a sensor, a strategy must be set:
client.sensor.fruit_result.set_strategy('event')
# If the condition does not occur within the timeout (default 5s), we will
# get a TimeoutException
yield client.sensor.fruit_result.wait(
lambda reading: reading.status == 'nominal')
fruit = yield client.sensor.fruit_result.get_value()
print 'Fruit picked: ', fruit
# And see how the ?pick-fruit request responded by yielding on its future
pick_response = yield pick_response_future
print 'pick response: \n', pick_response
# Finally stop the ioloop so that the program exits
ioloop.stop()
# Note, katcp.resource_client.ThreadSafeKATCPClientResourceWrapper can be used to
# turn the client into a 'blocking' client for use in e.g. ipython. It will turn
# all functions that return tornado futures into blocking calls, and will bounce
# all method calls through the ioloop. In this case the ioloop must be started
# in a separate thread. katcp.ioloop_manager.IOLoopManager can be used to manage
# the ioloop thread.
ioloop.add_callback(client.start)
ioloop.add_callback(demo)
ioloop.start()
Writing your own Server¶
Creating a server requires sub-classing DeviceServer
. This class already provides all the requests and inform
messages required by the KATCP protocol. However, its implementation requires a
little assistance from the subclass in order to function.
A very simple server example looks like:
import threading
import time
import random
from katcp import DeviceServer, Sensor, ProtocolFlags, AsyncReply
from katcp.kattypes import (Str, Float, Timestamp, Discrete,
request, return_reply)
server_host = ""
server_port = 5000
class MyServer(DeviceServer):
VERSION_INFO = ("example-api", 1, 0)
BUILD_INFO = ("example-implementation", 0, 1, "")
# Optionally set the KATCP protocol version and features. Defaults to
# the latest implemented version of KATCP, with all supported optional
# features
PROTOCOL_INFO = ProtocolFlags(5, 0, set([
ProtocolFlags.MULTI_CLIENT,
ProtocolFlags.MESSAGE_IDS,
]))
FRUIT = [
"apple", "banana", "pear", "kiwi",
]
def setup_sensors(self):
"""Setup some server sensors."""
self._add_result = Sensor.float("add.result",
"Last ?add result.", "", [-10000, 10000])
self._time_result = Sensor.timestamp("time.result",
"Last ?time result.", "")
self._eval_result = Sensor.string("eval.result",
"Last ?eval result.", "")
self._fruit_result = Sensor.discrete("fruit.result",
"Last ?pick-fruit result.", "", self.FRUIT)
self.add_sensor(self._add_result)
self.add_sensor(self._time_result)
self.add_sensor(self._eval_result)
self.add_sensor(self._fruit_result)
@request(Float(), Float())
@return_reply(Float())
def request_add(self, req, x, y):
"""Add two numbers"""
r = x + y
self._add_result.set_value(r)
return ("ok", r)
@request()
@return_reply(Timestamp())
def request_time(self, req):
"""Return the current time in seconds since the Unix Epoch."""
r = time.time()
self._time_result.set_value(r)
return ("ok", r)
@request(Str())
@return_reply(Str())
def request_eval(self, req, expression):
"""Evaluate a Python expression."""
r = str(eval(expression))
self._eval_result.set_value(r)
return ("ok", r)
@request()
@return_reply(Discrete(FRUIT))
def request_pick_fruit(self, req):
"""Pick a random fruit."""
r = random.choice(self.FRUIT + [None])
if r is None:
return ("fail", "No fruit.")
delay = random.randrange(1,5)
req.inform("Picking will take %d seconds" % delay)
def pick_handler():
self._fruit_result.set_value(r)
req.reply("ok", r)
self.ioloop.add_callback(
self.ioloop.call_later, delay, pick_handler)
raise AsyncReply
def request_raw_reverse(self, req, msg):
"""
A raw request handler to demonstrate the calling convention if
@request decorator are not used. Reverses the message arguments.
"""
# msg is a katcp.Message.request object
reversed_args = msg.arguments[::-1]
# req.make_reply() makes a katcp.Message.reply using the correct request
# name and message ID
return req.make_reply('ok', *reversed_args)
if __name__ == "__main__":
server = MyServer(server_host, server_port)
server.start()
server.join()
Notice that MyServer
has three special class attributes
VERSION_INFO
, BUILD_INFO
and
PROTOCOL_INFO
. VERSION_INFO
gives the version of the server
API. Many implementations might use the same
VERSION_INFO
. BUILD_INFO
gives the version of the software
that provides the device. Each device implementation should have a unique
BUILD_INFO
. PROTOCOL_INFO
is an instance of
ProtocolFlags
that describes the KATCP dialect spoken by the server. If
not specified, it defaults to the latest implemented version of KATCP, with all
supported optional features. Using a version different from the default may
change server behaviour; furthermore version info may need to be passed to the
@request
and @return_reply
decorators.
The setup_sensors()
method registers Sensor
objects with the device server. The base class uses this information to
implement the ?sensor-list
, ?sensor-value
and
?sensor-sampling
requests. add_sensor()
should be called once for each sensor the
device should contain. You may create the sensor objects inside
setup_sensors()
(as done in the example) or elsewhere if you wish.
Request handlers are added to the server by creating methods whose names start
with “request_”. These methods take two arguments – the client-request object
(abstracts the client socket and the request context) that the request came from,
and the request message. Notice that the message argument is missing from the
methods in the example. This is a result of the request()
decorator that has been applied to the methods.
The request()
decorator takes a list of
KatcpType
objects describing the request
arguments. Once the arguments have been checked they are passed in to the
underlying request method as additional parameters instead of the request
message.
The return_reply
decorator performs a
similar operation for replies. Once the request method returns a tuple (or list)
of reply arguments, the decorator checks the values of the arguments and
constructs a suitable reply message.
Use of the request()
and return_reply()
decorators is encouraged but entirely optional.
Message dispatch is handled in much the same way as described in the client
example, with the exception that there are no unhandled_request()
,
unhandled_reply()
or unhandled_request()
methods. Instead, the
server will log an exception.
Writing your own Async Server¶
To write a server in the typical tornado async style, modify the example above by adding the following imports
import signal
import tornado
from katcp import AsyncDeviceServer
Also replace class MyServer(DeviceServer) with class MyServer(AsyncDeviceServer) and replace the if __name__ == “__main__”: block with
@tornado.gen.coroutine
def on_shutdown(ioloop, server):
print('Shutting down')
yield server.stop()
ioloop.stop()
if __name__ == "__main__":
ioloop = tornado.ioloop.IOLoop.current()
server = MyServer(server_host, server_port)
# Hook up to SIGINT so that ctrl-C results in a clean shutdown
signal.signal(signal.SIGINT, lambda sig, frame: ioloop.add_callback_from_signal(
on_shutdown, ioloop, server))
ioloop.add_callback(server.start)
ioloop.start()
If multiple servers are started in a single ioloop, on_shutdown()
should
be modified to call stop()
on each server. This is needed to allow a clean
shutdown that adheres to the KATCP specification requirement that a #disconnect inform
is sent when a server shuts down.
Event Loops and Thread Safety¶
As of version 0.6.0, katcp-python was completely reworked to use Tornado as an event- and network library. A typical Tornado application would only use a single tornado.ioloop.IOLoop event-loop instance. Logically independent parts of the application would all share the same ioloop using e.g. coroutines to allow concurrent tasks.
However, to maintain backwards compatibility with the thread-semantics of older
versions of this library, it supports starting a tornado.ioloop.IOLoop
instance in a new thread for each client or server. Instantiating the
BlockingClient
or CallbackClient
client classes or the
DeviceServer
server class will implement the backward compatible
behaviour by default, while using AsyncClient
or
AsyncDeviceServer
will by default use tornado.ioloop.IOLoop.current()
as the ioloop (can be overridden using their set_ioloop methods), and won’t
enable thread safety by default (can be overridden using
AsyncDeviceServer.set_concurrency_options()
and
AsyncClient.enable_thread_safety()
)
Note that any message (request, reply, iform) handling methods should not
block. A blocking handler will block the ioloop, causing all timed operations
(e.g. sensor strategies), network io, etc. to block. This is particularly
important when multiple servers/clients share a single ioloop. A good solution
for handlers that need to wait on other tasks is to implement them as Tornado
coroutines. A DeviceServer
will not accept another request message
from a client connection until the request handler has completed / resolved its
future. Multiple outstanding requests can be handled concurrently by raising the
AsyncReply
exception in a request handler. It is then the
responsibility of the user to ensure that a reply is eventually sent using the
req object.
If DeviceServer.set_concurrency_options()
has handler_thread=True (the
default for DeviceServer
, AsyncDeviceServer
defaults to
False), all the requests to a server is serialised and handled in a separate
request handing thread. This allows request handlers to block without preventing
sensor strategy updates, providing backwards-compatible concurrency
semantics.
In the case of a purely network-event driven server or client, all user code would execute in the thread context of the server or client event loop. Therefore all handler functions must be non-blocking to prevent unresponsiveness. Unhandled exceptions raised by handlers running in the network event-thread are caught and logged; in the case of servers, an error reply including the traceback is sent over the network interface. Slow operations (such as picking fruit) may be delegated to another thread (if a threadsafe server is used), a callback (as shown in the request_pick_fruit handler in the server example) or tornado coroutine.
If a device is linked to processing that occurs independently of network events,
one approach would be a model thread running in the background. The KATCP
handler code would then defer requests to the model. The model must provide a
thread-safe interface to the KATCP code. If using an async server
(e.g. AsyncDeviceServer
or DeviceServer.set_concurrency_options()
called with thread_safe=False), all interaction with the device server needs
to be through the tornado.ioloop.Ioloop.add_callback()
method of the
server’s ioloop. The server’s ioloop instance can be accessed through its
ioloop attribute. If a threadsafe server (e.g. DeviceServer
with
default concurrency options) or client (e.g. CallbackClient
) is used,
all the public methods provided by this katcp library for sending !replies or
#informs are thread safe.
Updates to Sensor
objects using the public setter methods are always
thread-safe, provided that the same is true for all the observers attached to
the sensor. The server observers used to implement sampling strategies are
threadsafe, even if an async server is used.
Backwards Compatibility¶
Server Protocol Backwards Compatibility¶
A minor modification of the first several lines of the example in Writing your own Server suffices to create a KATCP v4 server:
from katcp import DeviceServer, Sensor, ProtocolFlags, AsyncReply
from katcp.kattypes import (Str, Float, Timestamp, Discrete,
request, return_reply)
from functools import partial
import threading
import time
import random
server_host = ""
server_port = 5000
# Bind the KATCP major version of the request and return_reply decorators
# to version 4
request = partial(request, major=4)
return_reply = partial(return_reply, major=4)
class MyServer(DeviceServer):
VERSION_INFO = ("example-api", 1, 0)
BUILD_INFO = ("example-implementation", 0, 1, "")
# Optionally set the KATCP protocol version as 4.
PROTOCOL_INFO = ProtocolFlags(4, 0, set([
ProtocolFlags.MULTI_CLIENT,
]))
The rest of the example follows as before.
Client Protocol Backwards Compatibility¶
The DeviceClient
client automatically detects the
version of the server if it can, see
Server KATCP Version Auto-detection. For a simple client
this means that no changes are required to support different KATCP
versions. However, the semantics of the messages might be different for
different protocol versions. Using the unpack_message
decorator with major=4 for reply or inform
handlers might help here, although it could use some improvement.
In the case of version auto-detection failing for a given server,
preset_protocol_flags
can be
used to set the KATCP version before calling the client’s start()
method.
How to Contribute¶
Everyone is welcome to contribute to the katcp-python project. If you don’t feel comfortable with writing core katcp we are looking for contributors to documentation or/and tests.
Another option is to report bugs, problems and new ideas as issues. Please be very detailed.
Workflow¶
A Git workflow with branches for each issue/feature is used.
- There is no special policy regarding commit messages. The first line should be short (50 chars or less) and contain summary of all changes. Additional detail can be included after a blank line.
- Pull requests are normally made to master branch. An exception is when hotfixing a release - in this case the merge target would be to the release branch.
reStructuredText and Sphinx¶
Documentation is written in reStructuredText and built with Sphinx - it’s easy to contribute. It also uses autodoc importing docstrings from the katcp package.
Source code standard¶
All code should be PEP8 compatible, with more details and exception described in our guidelines.
Note
The accepted policy is that your code cannot introduce more issues than it solves!
You can also use other tools for checking PEP8 compliance for your personal use. One good example of such a tool is Flake8 which combines PEP8 and PyFlakes. There are plugins for various IDEs so that you can use your favourite tool easily.
Releasing a new version¶
From time to time a new version is released. Anyone who wishes to see some features of the master branch released is free to request a new release. One of the maintainers can make the release. The basic steps required are as follows:
- Pick a version number
- Semantic version numbering is used: <major>.<minor>.<patch>
- Small changes are done as patch releases. For these the version number should correspond the current development number since each release process finishes with a version bump.
- Patch release example:
0.6.3.devN
(current master branch)- changes to
0.6.3
(the actual release) - changes to
0.6.4.dev0
(bump the patch version at the end of the release process)
- Create an issue in Github
This is to inform the community that a release is planned.
Use a checklist similar to the one below:
Task list:- [ ] Read steps in the How to Contribute docs for making a release- [ ] Edit the changelog and release notes files- [ ] Make sure Jenkins tests are still passing on master branch- [ ] Make sure the documentation is updated for master (readthedocs)- [ ] Create a release tag on GitHub, from master branch- [ ] Make sure the documentation is updated for release (readthedocs)- [ ] Upload the new version to PyPI- [ ] Fill the release description on GitHub- [ ] Close this issueA check list is this form on github can be ticked off as the work progresses.
- Make a branch from
master
to prepare the release - Example branch name:
user/ajoubert/prepare-v0.6.3
. - Edit the
CHANGELOG
and release notes (indocs/releasenotes.rst
). Include all pull requests since the previous release. - Create a pull request to get these changes reviewed before proceeding.
- Example branch name:
- Make sure Jenkins is OK on
master
branch - All tests on Jenkins must be passing. If not, bad luck - you’ll have to fix it first, and go back a few steps…
- Make sure the documentation is ok on master
- Log in to https://readthedocs.org.
- Get account permissions for https://readthedocs.org/projects/katcp-python from another maintainer, if necessary.
- Readthedocs should automatically build the docs for each:
- push to master (latest docs)
- new tags (e.g v0.6.3)
- If it doesn’t work automatically, then:
- Trigger manually here: https://readthedocs.org/projects/katcp-python/builds/
- Create a release tag on GitHub
- On the Releases page, use “Draft a new release”.
- Tag must match the format of previous tags, e.g.
v0.6.3
. - Target must be the
master
branch.
- Make sure the documentation is updated for the newly tagged release
- If the automated build doesn’t work automatically, then:
- Trigger manually here: https://readthedocs.org/projects/katcp-python/builds/
- Set the new version to “active” here: https://readthedocs.org/dashboard/katcp-python/versions/
- Upload the new version to PyPI
- Log in to https://pypi.org.
- Get account permissions for katcp from another contributor, if necessary.
- If necessary, pip install twine: https://pypi.org/project/twine/
- Build update from the tagged commit:
$ git clean -xfd # Warning - remove all non-versioned files and directories
$ git fetch
$ git checkout v0.6.3
$ python setup.py sdist bdist_wheel
$ python3 setup.py bdist_wheel
- Upload to testpypi, and make sure all is well:
$ twine upload -r testpypi dist/katcp-0.6.3.tar.gz
$ twine upload -r testpypi dist/katcp-0.6.3-py2-none-any.whl
$ twine upload -r testpypi dist/katcp-0.6.3-py3-none-any.whl
- Test installation (in a virtualenv):
$ pip install katcp
$ pip install -U -i https://test.pypi.org/simple/ katcp
- Upload the source tarball and wheel to the real PyPI:
$ twine upload dist/katcp-0.6.3.tar.gz
$ twine upload dist/katcp-0.6.3-py2-none-any.whl
$ twine upload dist/katcp-0.6.3-py3-none-any.whl
- Fill in the release description on GitHub
- Content must be the same as the details in the changelog.
- Close off release issue in Github
- All the items on the check list should be ticked off by now.
- Close the issue.