chrysn/aiocoap

How to simultaneously observe multiple resources?

WattageGuy opened this issue · 6 comments

Python version: 3.9.6 (default, Feb 3 2024, 15:58:27)
[Clang 15.0.0 (clang-1500.3.9.4)]
aiocoap version: 0.4.7
Modules missing for subsystems:
dtls: missing DTLSSocket
oscore: missing cbor2, cryptography, filelock, ge25519
linkheader: everything there
prettyprint: missing cbor2, termcolor, pygments
Python platform: darwin
Default server transports: tcpserver:tcpclient:tlsserver:tlsclient:simple6:simplesocketserver
Selected server transports: tcpserver:tcpclient:tlsserver:tlsclient:simple6:simplesocketserver
Default client transports: tcpclient:tlsclient:simple6
Selected client transports: tcpclient:tlsclient:simple6
SO_REUSEPORT available (default, selected): True, True

My lwm2m client works to observe any resource on Leshan (lwm2m server) but not to observe 2 or more. Some times it works with two but its not stable, sometimes both resources gets the same value, in most case the seconds observe also gets the first observes value but not the other way around (as seen in the pictures).
Skärmavbild 2024-04-08 kl  15 27 48
Skärmavbild 2024-04-08 kl  15 27 44

I am pretty unexperienced but I have monitored the "Sending message" in message manager and the outgoing messages seems correct, correct value to correct resource. So I dont know where or why this happens. I have also changed one line in the resource.py to get the uri_path in the request. stripped = request.copy(uri_path=request.opt.uri_path)

This is my code handling the observe:

    async def handle_observe(self, request):
        path = request.opt.uri_path
        plen = len(path)
        if plen == 1:
            obs = f'observe_{path[0]}'
        elif plen == 2:
            obs = f'observe_{path[0]}_{path[1]}'
        elif plen == 3:
            obs = f'observe_{path[0]}_{path[1]}_{path[2]}'
        else:
            return Message(code=Code.BAD_REQUEST)

        def _notifier():
            self.updated_state(response=self.encoder.encode(path))

        try:
            obs_method = eval(obs)
            cancel = request.opt.observe == '0'
            _kwargs = dict(model=self.model,
                           path=path,
                           payload=request.payload,
                           content_format=request.opt.content_format,
                           cancel=cancel,
                           notifier=_notifier)
            obs_method(None, **_kwargs)
            print("Triggered observe")
            return self.encoder.encode(path)
        except NameError:
            pass
        return Message(code=Code.METHOD_NOT_ALLOWED)

    async def render_get(self, request):
        if request.opt.observe is not None:
            log.debug(f'observe on {"/".join(request.opt.uri_path)}')
            return await self.handle_observe(request)
        else:
            log.debug(f'read on {"/".join(request.opt.uri_path)}')
            return self.handle_read(request.opt.uri_path)`

Some what related to #146

I did some Wireshark and I looks like /2 gets the value of /1 in the CON some times.
When correct value is sent the packet has some 0HE value, no idea what this is.
Skärmavbild 2024-04-08 kl  15 59 20
Skärmavbild 2024-04-08 kl  16 02 38

And when wrong value (value from /1) it is -HE:
Skärmavbild 2024-04-08 kl  15 59 41

Edit: This seems to be the checksum

Just to avoid confusion with other issues: This is unrelated to 146 (that is about the client side). This issue here is about the CoAP server side, which for some reasons LwM2M calls the client.

To help you here I'd have to understand what you are doing, and the code you copied in is insufficient for that. Do you have a pointer to your full source code?

Okay sorry I dont know exactly what im doing, still trying to understand this CoAP stuff. Here is the project: https://github.com/WattageGuy/lwm2mclient-BLE-gateway

Any clue yet @chrysn im in a bit of hurry with this project 😅

@WattageGuy - Any progress on this issue? I'm seeing what I believe is the same anomaly. What I have noticed is that the tokens between more than one observation are being mis-assigned. Example, if I have an observation for battery_level that is using token "a1b1c1d1e1f1" and an observation for "current_time" that is using token "a2b2c2d2e2f2." It feels like updated_state() method may be mishandling this in some way. I'm thinking about creating a content message to replace the updated.state() message creation to see if that addresses the token handling.