Open aellwein opened 5 years ago
This used to work a while ago with my lwm2mclient project, but i haven't used it long ago.
Brief response before I find the time to go into details: The Site (now) strips away all options it processes -- that's required to allow nested sites, and allows resources to err out if they encounter mandatory-to-process options. (A resource handler should not need to deal with the path (or the Uri-Host, for that matter) any more, and the site strips them away just as blockwise assembly strips away block options).
I'm not fully happy with the requests API yet, and having both an "original options" and "remaining options" list around would be a possibility, but to find a good design there: What's your need for having the path options around in a handler that was, as in your example, already constructed with the knowledge of being a "3_0" handler?
(Note to self: Add an FAQ entry about this.)
Well, the original idea was to provide "generic" GET/PUT/... etc. handlers, which is then to be customized by the client's user. In Lightweight M2M world, CoAP resources represent parts of device functionality, so called "objects" located at defined paths, like Device (/3), Firmware Update (/5), Location (/6) etc. objects being represented by instances (/3/0 means Device object instance 0 etc.) and then their attributes mapped to the last path segment. The CoAP methods mimic the operation on the object/object's attribute, like GET /3/0 would mean "read Manufacturer attribute of the Device Object". To make the model as flexible as possible, i decided to provide the representation of attributes in a separate JSON file which is loaded at startup. The user of the client is up to implement the missing operation and for that the knowledge of "what is being accessed/changed", i.e. the Uri-path (not the host) is required. So for instance, an object Device being handled with one resource handler registered at ("3", "0") and knowing about the attributes by their numbers on the path:
Without the uri-path, i would not know in render_get
of Device resource, which attribute of device is being accessed/changed, unless i would register a handler on per-attribute basis (which i consider to be ugly).
On Sun, May 19, 2019 at 10:34:10AM -0700, Alex Ellwein wrote:
Well, the original idea was to provide "generic" GET/PUT/... etc. handlers, which is then to be customized by the client's user.
Currently I'd see different ways to go about this, either:
if you want to register each resource separately to aiocoap: map their
prefix into them at creation time (root.add_resource(['3', '0'], MyResource((3, 0)))
) -- but I don't see much benefit to that if you
implement something generic anyway
if you build something that is only ever LwM2M and no other resources,
or can use an alternative path (</oma>;rt="oma.lwm2m"
and thus items
like /oma/3/0/1
), you use the marker class
aiocoap.resource.PathCapable
as a parent of your resource class, and
register it as root.add_resource([], MyResource())
or (['oma'], ...)
A site will recognize this handler as a sub-site and send it the request with the (remaining, if a prefix is present) components intact.
if you want to use the unprefixed style and still have non-OMA resources around, you could subclass Site about like this:
class OMASite(resource.Site):
async def render(self, request):
numericpath = extract_numeric_path(request)
if numericpath is None:
return await super().render(request)
else:
return await self.lwm2m_handler.render(numericpath, request)
(The last option is a bit cumbersome compared to the second, but that's iMO a consequence of the lwm2m application not being designed according to RFC7320).
Would any of those work in your use case, or would you still prefer to have the ability to access the original request path in a single handler?
Thanks for the detailed response.
Because i cannot ensure that the link header information always contained in the resource (IIRC some older Leshan server versions don't provide it, i'm also unsure about other LwM2M implementations so i'm expecting bad behavior here), i would rather tend to implement the latter alternative, it also gives me the chance to pass additional information from the original request, if i would need to.
Best regards, Alex
Hi @chrysn,
it seems that the request passed to
render_get()
method missing theuri_path
option, which is required in most use cases.Reproducable with aiocoap==0.3 and aiocoap==0.4a1.
See the test & output below:
Output: