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 object

The 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.