aiocoap.protocol module

This module contains the classes that are responsible for keeping track of messages:

  • Context roughly represents the CoAP endpoint (basically a UDP socket) – something that can send requests and possibly can answer incoming requests.
  • a Request gets generated whenever a request gets sent to keep track of the response
  • a Responder keeps track of a single incoming request
class aiocoap.protocol.Context(loop=None, serversite=None, loggername='coap')

Bases: asyncio.protocols.DatagramProtocol, aiocoap.interfaces.RequestProvider

An object that passes messages between an application and the network

A Context gets bound to a network interface as an asyncio protocol. It manages the basic CoAP network mechanisms like message deduplication and retransmissions, and delegates management of blockwise transfer as well as the details of matching requests with responses to the Request and Responder classes.

In that respect, a Context (as currently implemented) is also an endpoint. It is anticipated, though, that issues arise due to which the implementation won’t get away with creating a single socket, and that it will be required to deal with multiple endpoints. (E.g. the V6ONLY=0 option is not portable to some OS, and implementations might need to bind to different ports on different interfaces in multicast contexts). When those distinctions will be implemented, message dispatch will stay with the context, which will then deal with the individual endpoints.

In a way, a Context is the single object all CoAP messages that get treated by a single application pass by.

Context creation and destruction

Instead of passing a protocol factory to the asyncio loop’s create_datagram_endpoint method, the following convenience functions are recommended for creating a context:

classmethod create_client_context(*, dump_to=None, loggername='coap', loop=None)

Create a context bound to all addresses on a random listening port.

This is the easiest way to get an context suitable for sending client requests.

classmethod create_server_context(site, bind=('::', 5683), *, dump_to=None, loggername='coap-server', loop=None)

Create an context, bound to all addresses on the CoAP port (unless otherwise specified in the bind argument).

This is the easiest way to get a context suitable both for sending client and accepting server requests.

If you choose to create the context manually, make sure to wait for its ready future to complete, as only then can messages be sent.

shutdown()

Take down the listening socket and stop all related timers.

After this coroutine terminates, and once all external references to the object are dropped, it should be garbage-collectable.

This method may take the time to inform communications partners of stopped observations (but currently does not).

Dispatching messages

A context’s public API consists of the send_message() function, the outgoing_requests, incoming_requests and outgoing_obvservations dictionaries, and the serversite object, but those are not stabilized yet, and for most applications the following convenience functions are more suitable:

request(request, **kwargs)

TODO: create a proper interface to implement and deprecate direct instanciation again

multicast_request(request)

If more control is needed, eg. with observations, create a Request yourself and pass the context to it.

Other methods and properties

The remaining methods and properties are to be considered unstable even when the project reaches a stable version number; please file a feature request for stabilization if you want to reliably access any of them.

(Sorry for the duplicates, still looking for a way to make autodoc list everything not already mentioned).

outgoing_requests = None

Unfinished outgoing requests (identified by token and remote)

incoming_requests = None

Unfinished incoming requests. (path-tuple, remote): Request

outgoing_observations = None

Observations where this context acts as client. (token, remote) -> weak(ClientObservation)

incoming_observations = None

Observation where this context acts as server. (token, remote) -> ServerObservation. This is managed by :cls:ServerObservation and Responder.handle_observe_request().

shutdown()

Take down the listening socket and stop all related timers.

After this coroutine terminates, and once all external references to the object are dropped, it should be garbage-collectable.

This method may take the time to inform communications partners of stopped observations (but currently does not).

fill_remote(message)
send_message(message, exchange_monitor=None)

Encode and send message. This takes care of retransmissions (if CON), message IDs and rate limiting, but does not hook any events to responses. (Use the Request class or responding resources instead; those are the typical callers of this function.)

If notification about the progress of the exchange is required, an ExchangeMonitor can be passed in, which will receive the appropriate callbacks.

next_token()

Reserve and return a new Token for request.

request(request, **kwargs)

TODO: create a proper interface to implement and deprecate direct instanciation again

multicast_request(request)
classmethod create_client_context(*, dump_to=None, loggername='coap', loop=None)

Create a context bound to all addresses on a random listening port.

This is the easiest way to get an context suitable for sending client requests.

classmethod create_server_context(site, bind=('::', 5683), *, dump_to=None, loggername='coap-server', loop=None)

Create an context, bound to all addresses on the CoAP port (unless otherwise specified in the bind argument).

This is the easiest way to get a context suitable both for sending client and accepting server requests.

kill_transactions(remote, exception=<class 'aiocoap.error.CommunicationKilled'>)

Abort all pending exchanges and observations to a given remote.

The exact semantics of this are not yet completely frozen – currently, pending exchanges are treated as if they timeouted, server sides of observations are droppedn and client sides of observations receive an errback.

Requests that are not part of an exchange, eg. NON requests or requests that are waiting for their responses after an empty ACK are currently not handled.

class aiocoap.protocol.BaseRequest

Bases: object

Common mechanisms of Request and MulticastRequest

class aiocoap.protocol.Request(protocol, app_request, exchange_monitor_factory=<function Request.<lambda>>, handle_blockwise=True)

Bases: aiocoap.protocol.BaseRequest, aiocoap.interfaces.Request

Class used to handle single outgoing request.

Class includes methods that handle sending outgoing blockwise requests and receiving incoming blockwise responses.

cancel()
send_request(request)

Send a request or single request block.

This method is used in 3 situations: - sending non-blockwise request - sending blockwise (Block1) request block - asking server to send blockwise (Block2) response block

handle_response(response)
process_block1_in_response(response)

Process incoming response with regard to Block1 option.

process_block2_in_response(response)

Process incoming response with regard to Block2 option.

handle_final_response(response)
register_observation(response)
response_raising

An awaitable that returns if a response comes in and is successful, otherwise raises generic network exception or a error.ResponseWrappingError for unsuccessful responses.

Experimental Interface.

response_nonraising

An awaitable that rather returns a 500ish fabricated message (as a proxy would return) instead of raising an exception.

Experimental Interface.

class aiocoap.protocol.MulticastRequest(protocol, request)

Bases: aiocoap.protocol.BaseRequest

handle_response(response)
class aiocoap.protocol.Responder(protocol, request, exchange_monitor_factory=<function Responder.<lambda>>)

Bases: object

Handler for an incoming request or (in blockwise) a group thereof

Class includes methods that handle receiving incoming blockwise requests (only atomic operation on complete requests), searching for target resources, preparing responses and sending outgoing blockwise responses.

To keep an eye on exchanges going on, a factory for ExchangeMonitor can be passed in that generates a monitor for every single message exchange created during the response.

handle_next_request(request)
process_block1_in_request(request)

Process an incoming request while in block1 phase.

This method is responsible for finishing the app_request future and thus indicating that it should not be called any more, or scheduling itself again.

dispatch_request(initial_block)

Dispatch incoming request - search context resource tree for resource in Uri Path and call proper CoAP Method on it.

respond_with_error(request, code, payload)

Helper method to send error response to client.

respond(app_response, request)

Take application-supplied response and prepare it for sending.

process_block2_in_request(request)

Process incoming request with regard to Block2 option

Method is recursive - calls itself until all response blocks are sent to client.

send_non_final_response(response, request)

Helper method to send a response to client, and setup a timeout for client. This also registers the responder with the protocol again to receive the next message.

send_final_response(response, request)
send_response(response, request)

Send a response or single response block.

This method is used in 4 situations: - sending success non-blockwise response - asking client to send blockwise (Block1) request block - sending blockwise (Block2) response block - sending any error response

send_empty_ack(request)

Send separate empty ACK when response preparation takes too long.

Currently, this can happen only once per Responder, that is, when the last block1 has been transferred and the first block2 is not ready yet.

handle_observe_request(request)
handle_observe_response(request, response)

Modify the response according to the Responder’s understanding of the involved observation (eg. drop the observe flag it’s not involved in an observation or the observation was cancelled), and update the Responder/context if the response modifies the observation state (eg. by being unsuccessful).

class aiocoap.protocol.ExchangeMonitor

Bases: object

Callback collection interface to keep track of what happens to an exchange.

Callbacks will be called in sequence: enqueued{0,1} sent retransmitted{0,MAX_RETRANSMIT} (timeout | rst | cancelled | response); everything after sent only gets called if the messae that initiated the exchange was a CON.

enqueued()
sent()
retransmitted()
timeout()
rst()
cancelled()
response(message)
class aiocoap.protocol.ServerObservation(original_protocol, original_request, requester_log)

Bases: object

An active CoAP observation inside a server is described as a ServerObservation object.

It keeps a complete copy of the original request for simplicity (while it actually would only need parts of that request, like the accept option).

A ServerObservation has two boolean states: accepted and cancelled. It is originally neither, gets accepted when a ObservableResource.add_observation() method does accept() it, and gets cancelled by incoming packages of the same identifier, RST/timeout on notifications or the observed resource. Beware that an accept can happen after cancellation if the client changes his mind quickly, but the resource takes time to decide whether it can be observed.

accept(cancellation_callback)
deregister(reason)
identifier
static request_key(request)
trigger(response=None)
class ObservationExchangeMonitor(observation)

Bases: aiocoap.protocol.ExchangeMonitor

These objects feed information about the success or failure of a response back to the observation.

Note that no information flows to the exchange monitor from the observation, so they may outlive the observation and need to check if it’s not already cancelled before cancelling it.

enqueued()
sent()
rst()
timeout()
class aiocoap.protocol.ClientObservation(original_request)

Bases: object

register_callback(callback)

Call the callback whenever a response to the message comes in, and pass the response to it.

register_errback(callback)

Call the callback whenever something goes wrong with the observation, and pass an exception to the callback. After such a callback is called, no more callbacks will be issued.

callback(response)

Notify all listeners of an incoming response

error(exception)

Notify registered listeners that the observation went wrong. This can only be called once.

cancel()

Cease to generate observation or error events. This will not generate an error by itself.