aiocoap.resource module

Basic resource implementations

A resource in URL / CoAP / REST terminology is the thing identified by a URI.

Here, a Resource is the place where server functionality is implemented. In many cases, there exists one persistent Resource object for a given resource (eg. a TimeResource() is responsible for serving the /time location). On the other hand, an aiocoap server context accepts only one thing as its serversite, and that is a Resource too (typically of the Site class).

Resources are most easily implemented by deriving from Resource and implementing render_get, render_post and similar coroutine methods. Those take a single request message object and must return a aiocoap.Message object or raise an error.RenderableError (eg. raise UnsupportedMediaType()).

To serve more than one resource on a site, use the Site class to dispatch requests based on the Uri-Path header.

aiocoap.resource.hashing_etag(request, response)

Helper function for render_get handlers that allows them to use ETags based on the payload’s hash value

Run this on your request and response before returning from render_get; it is safe to use this function with all kinds of responses, it will only act on 2.05 Content messages (and those with no code set, which defaults to that for GET requests). The hash used are the first 8 bytes of the sha1 sum of the payload.

Note that this method is not ideal from a server performance point of view (a file server, for example, might want to hash only the stat() result of a file instead of reading it in full), but it saves bandwith for the simple cases.

>>> from aiocoap import *
>>> req = Message(code=GET)
>>> hash_of_hello = b'\xaa\xf4\xc6\x1d\xdc\xc5\xe8\xa2'
>>> req.opt.etags = [hash_of_hello]
>>> resp = Message(code=CONTENT)
>>> resp.payload = b'hello'
>>> hashing_etag(req, resp)
>>> resp                                            
<aiocoap.Message at ... 2.03 Valid ... 1 option(s)>
class aiocoap.resource.Resource

Bases: _ExposesWellknownAttributes, Resource

Simple base implementation of the interfaces.Resource interface

The render method delegates content creation to render_$method methods (render_get, render_put etc), and responds appropriately to unsupported methods. Those messages may return messages without a response code, the default render method will set an appropriate successful code (“Content” for GET/FETCH, “Deleted” for DELETE, “Changed” for anything else). The render method will also fill in the request’s no_response code into the response (see interfaces.Resource.render()) if none was set.

Moreover, this class provides a get_link_description method as used by .well-known/core to expose a resource’s .ct, .rt and .if_ (alternative name for if as that’s a Python keyword) attributes. Details can be added by overriding the method to return a more comprehensive dictionary, and resources can be hidden completely by returning None.

async needs_blockwise_assembly(request)

Indicator to the protocol.Responder about whether it should assemble request blocks to a single request and extract the requested blocks from a complete-resource answer (True), or whether the resource will do that by itself (False).

async render(request)

Return a message that can be sent back to the requester.

This does not need to set any low-level message options like remote, token or message type; it does however need to set a response code.

A response returned may carry a no_response option (which is actually specified to apply to requests only); the underlying transports will decide based on that and its code whether to actually transmit the response.

async render_to_pipe(request: Pipe)

Create any number of responses (as indicated by the request) into the request stream.

This method is provided by the base Resource classes; if it is overridden, then render(), needs_blockwise_assembly() and add_observation() are not used any more. (They still need to be implemented to comply with the interface definition, which is yet to be updated).

class aiocoap.resource.ObservableResource

Bases: Resource, ObservableResource

async add_observation(request, serverobservation)

Before the incoming request is sent to render(), the add_observation() method is called. If the resource chooses to accept the observation, it has to call the serverobservation.accept(cb) with a callback that will be called when the observation ends. After accepting, the ObservableResource should call serverobservation.trigger() whenever it changes its state; the ServerObservation will then initiate notifications by having the request rendered again.

update_observation_count(newcount)

Hook into this method to be notified when the number of observations on the resource changes.

updated_state(response=None)

Call this whenever the resource was updated, and a notification should be sent to observers.

async render_to_pipe(request: Pipe)

Create any number of responses (as indicated by the request) into the request stream.

This method is provided by the base Resource classes; if it is overridden, then render(), needs_blockwise_assembly() and add_observation() are not used any more. (They still need to be implemented to comply with the interface definition, which is yet to be updated).

Given a LinkFormat object, render it to a response message, picking a suitable conent format from a given request.

It returns a Not Acceptable response if something unsupported was queried.

It makes no attempt to modify the URI reference literals encoded in the LinkFormat object; they have to be suitably prepared by the caller.

class aiocoap.resource.WKCResource(listgenerator, impl_info='https://christian.amsuess.com/tools/aiocoap/#version-0.4.7.post0', **kwargs)

Bases: Resource

Read-only dynamic resource list, suitable as .well-known/core.

This resource renders a link_header.LinkHeader object (which describes a collection of resources) as application/link-format (RFC 6690).

The list to be rendered is obtained from a function passed into the constructor; typically, that function would be a bound Site.get_resources_as_linkheader() method.

This resource also provides server implementation information link; server authors are invited to override this by passing an own URI as the impl_info parameter, and can disable it by passing None.

ct = '40'
async render_get(request)
class aiocoap.resource.PathCapable

Bases: object

Class that indicates that a resource promises to parse the uri_path option, and can thus be given requests for render()-ing that contain a uri_path

class aiocoap.resource.Site

Bases: ObservableResource, PathCapable

Typical root element that gets passed to a Context and contains all the resources that can be found when the endpoint gets accessed as a server.

This provides easy registration of statical resources. Add resources at absolute locations using the add_resource() method.

For example, the site at

>>> site = Site()
>>> site.add_resource(["hello"], Resource())

will have requests to </hello> rendered by the new resource.

You can add another Site (or another instance of PathCapable) as well, those will be nested and integrally reported in a WKCResource. The path of a site should not end with an empty string (ie. a slash in the URI) – the child site’s own root resource will then have the trailing slash address. Subsites can not have link-header attributes on their own (eg. rt) and will never respond to a request that does not at least contain a single slash after the the given path part.

For example,

>>> batch = Site()
>>> batch.add_resource(["light1"], Resource())
>>> batch.add_resource(["light2"], Resource())
>>> batch.add_resource([], Resource())
>>> s = Site()
>>> s.add_resource(["batch"], batch)

will have the three created resources rendered at </batch/light1>, </batch/light2> and </batch/>.

If it is necessary to respond to requests to </batch> or report its attributes in .well-known/core in addition to the above, a non-PathCapable resource can be added with the same path. This is usually considered an odd design, not fully supported, and for example doesn’t support removal of resources from the site.

async needs_blockwise_assembly(request)

Indicator to the protocol.Responder about whether it should assemble request blocks to a single request and extract the requested blocks from a complete-resource answer (True), or whether the resource will do that by itself (False).

async render(request)

Return a message that can be sent back to the requester.

This does not need to set any low-level message options like remote, token or message type; it does however need to set a response code.

A response returned may carry a no_response option (which is actually specified to apply to requests only); the underlying transports will decide based on that and its code whether to actually transmit the response.

async add_observation(request, serverobservation)

Before the incoming request is sent to render(), the add_observation() method is called. If the resource chooses to accept the observation, it has to call the serverobservation.accept(cb) with a callback that will be called when the observation ends. After accepting, the ObservableResource should call serverobservation.trigger() whenever it changes its state; the ServerObservation will then initiate notifications by having the request rendered again.

add_resource(path, resource)
remove_resource(path)
get_resources_as_linkheader()
async render_to_pipe(request: Pipe)

Create any number of responses (as indicated by the request) into the request stream.

This method is provided by the base Resource classes; if it is overridden, then render(), needs_blockwise_assembly() and add_observation() are not used any more. (They still need to be implemented to comply with the interface definition, which is yet to be updated).