eclipse-wakaama / wakaama

Eclipse Wakaama is a C implementation of the Open Mobile Alliance's LightWeight M2M protocol (LWM2M).
BSD 3-Clause "New" or "Revised" License
497 stars 374 forks source link

Not acceptable to replace subset of resources with object write? #674

Open H732948 opened 1 year ago

H732948 commented 1 year ago

Hi,

I have an object with three multiple type resources. I would like to be able to write either all of them, a subset of them, or one of them using object replace.

If I want to write new values to a subset of the resources using an object replace, I specify the new values for the resources I want to write as well as no value, empty brackets, for the resources I don't want to write. But that makes Wakaama return "NOT_ACCEPTABLE".

I can't find any mention in the LWM2M-specification (v. 1.0) that you're not allowed to write an empty instance to a resource. Is this a bug in Wakaama or am I using the wrong method to achieve what I want?

Thank you and best regards, Sam

sbernard31 commented 1 year ago

(warning I don't really know Wakaama behavior but I can try to answer at LWM2M level)

Just to be sure what you call "object replace" is "send a WRITE request targeting an object with replace mode" ?

But targeting an object is not allowed by the LWM2M specification, object instance Id is required.

Parameter Required Default Value Notes
Object ID Yes - Indicates the Object.
Object Instance ID Yes - Indicates the Object Instance to write.
Resource ID No - Indicates the Resource to write. If the final target is not a Resource Instance (see below), the payload is the new value for the Resource.The payload is the new value for the Resource. If no Resource ID is indicated, the Resource Instance ID MUST NOT be indicated , then the value included payload is an Object Instance containing the Resource values.
Resource Instance ID No - Indicates the Resource Instance to write. An error MUST be returned by the Client, if the Resource ID is absent, if the targeted Resource is not defined as a Multiple-Instance Resource, or if the targeted Resource Instance doesn't exist.
New Value Yes - The new value included in the payload to update the Object Instance, a Resource or a Resource Instance.

(source : LWM2M v1.1.1@core§Table: 6.3.3.-1 Write Parameters)

So let's suppose you "object replace" means "Send a WRITE request targeting object instance with replace mode".

If I want to write new values to a subset of the resources using an object replace, I specify the new values for the resources I want to write as well as no value, empty brackets, for the resources I don't want to write.

Using Replace Mode will erase existing LWM2M node with the new one you provide. The specification says :

"Replace: replaces the Object Instance or the Resource(s) with the new value provided in the "Write" operation. When the Resource is a Multiple-Instance Resource, the existing array of Resource Instances is replaced to the condition the LwM2M Client authorizes that operation."

(source : LWM2M v1.1.1@core§6.3.3. Write Operation/V1_1_1-20190617-A/HTML-Version/OMA-TS-LightweightM2M_Core-V1_1_1-20190617-A.html#6-3-3-0-633-Write-Operation)

So my understanding is that you don't need to put resource you don't want to write.

pehrnord commented 1 year ago

Hi and thanks for the speedy response! I am also involved with this, so I would like to clarify and make sure we understand correctly: What we have is an object instance with three multiple resources. We would like to, in one write, be able to clear all resource instances on a resource (replace with 0 resource instances), and replace all resource instances with new instances in another of the three resources.

Assuming we "Send a WRITE request targeting object instance with replace mode" in this case, should we:

  1. Issue a write with 0 resource instances to the resource we wish to clear (this causes wakaama to return NOT_ACCEPTABLE), or
  2. Not address that resource at all and only target the resources which will have new instances, which would then clear the unaddressed resources implicitly

Our implementation uses lwm2m v1.0 if that matters

sbernard31 commented 1 year ago

Our implementation uses lwm2m v1.0 if that matters

AFAIK, on this particular point the LWM2M specification is identical in v1.0.x and v1.1.x :

"Replace: replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. When the Resource is a Multiple-Instance Resource, the existing array of Resource Instances is replaced under the condition that the LwM2M Client authorizes that operation."

Source : http://openmobilealliance.org/release/LightweightM2M/V1_0_2-20180209-A/OMA-TS-LightweightM2M-V1_0_2-20180209-A.pdf

pehrnord commented 1 year ago

"Replace: replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation.

I would then assume that it is option 1 that is the correct way to do this:

  1. Issue a write with 0 resource instances to the resource we wish to clear (this causes wakaama to return NOT_ACCEPTABLE)

Meaning this https://github.com/eclipse/wakaama/blob/89b9d3efda98ce66c33c233f4a5d9cdcb3f45aa7/core/objects.c#L391 is a bug?

Might be because of this conflict in the spec? https://github.com/OpenMobileAlliance/OMA_LwM2M_for_Developers/issues/551

sbernard31 commented 1 year ago

Assuming we "Send a WRITE request targeting object instance with replace mode" in this case, should we:

  1. Issue a write with 0 resource instances to the resource we wish to clear (this causes wakaama to return NOT_ACCEPTABLE), or
    1. Not address that resource at all and only target the resources which will have new instances, which would then clear the unaddressed resources implicitly

Oh OK, I didn't get the question, It's much clear now

I guess generally both should works but the specification doesn't explicitly say how this should be encoded ... so this could differ from one implementation to another And this is also depend of the Content Format you're using.

E.g : For SenML+json from LWM2M v1.1.x : we never get a clear answer about that : https://github.com/OpenMobileAlliance/OMA_LwM2M_for_Developers/issues/494

I tested with Leshan and it support both with some different behavior depending on content format.

Let's suppose you have an instance 0 of object 3441 which looks like :

/3441/0/1110 :  { 0 = "string1",  1 = "string2" }
/3441/0/1120 :  { 1= 11, 1 = 22 }

1. if you try to write

/3441/0/1110 :  { 3 = "newString"}

All content format will behave the same way and resource /3441/0/1120 will not exist anymore, if you try to read it you get 404 NON_FOUND.

2. if you try to write

/3441/0/1110 :  { 3 = "newString"}
/3441/0/1120 :  { }

All content format will behave like above :point_up: (return NOT FOUND) except for TLV. For TLV, if you try to read /3441/0/1120, the resource exists and you get an 2.05 Content with an empty resource.

sbernard31 commented 1 year ago

Meaning this https://github.com/eclipse/wakaama/blob/89b9d3efda98ce66c33c233f4a5d9cdcb3f45aa7/core/objects.c#L391 is a bug?

Not sure it's really a bug as the specification is inconsistent but maybe it would be better to support both case. (Again I'm not an active committer on Wakaama)

sbernard31 commented 1 year ago

Did you try, the 2. way ? Does it work ?

pehrnord commented 1 year ago

From my understanding, when we try method 2, our wakaama client rejects the "/3441/0/1120 : { }" part of the write with error code COAP_406_NOT_ACCEPTABLE. And when trying method 1, the leshan server will not perform the write because both resources in our case are marked as Mandatory. In our case, TLV is used

sbernard31 commented 1 year ago

Arf mandatory resource ... another not clear topic of the LWM2M specification : https://github.com/OpenMobileAlliance/OMA_LwM2M_for_Developers/issues/77#issuecomment-1262430200

And when trying method 1, the leshan server will not perform the write because both resources in our case are marked as Mandatory.

That's surprise me, I don't remember there is a kind of checks like this... :thinking: Could you share the error / stacktrace ? Or maybe you just talk about leshan-server-demo UI ?

sbernard31 commented 1 year ago

I don't remember there is this kind of check at Leshan Server side but anyway if it exits it make sense.

Is it a custom Model created by you OR a registered Model from OMA ? Maybe you could change the model (as workaround)?

But again I think the best will be to support method 2 at wakaama side.

It would be great to get feedback from wakaama team ? @rettichschnidi @tuve @mlasch

pehrnord commented 1 year ago

I will see if I can find out more info tomorrow

pehrnord commented 1 year ago

All content format will behave like above ☝️ (return NOT FOUND) except for TLV. For TLV, if you try to read /3441/0/1120, the resource exists and you get an 2.05 Content with an empty resource.

A followup question for this: If we implement support for method 2 in wakaama, what should be returned when the resource is read in this case? NOT_FOUND or CONTENT + empty resource? It seems preferable to have TLV, json, senml behaving the same.

sbernard31 commented 1 year ago

It seems preferable to have TLV, json, senml behaving the same.

Ideally, I agree.

In practice, I think that an empty resource or no resource at all (NOT FOUND) is not the same semantically speaking. So ideally, when you write an empty resource, you should read an empty resource. And if you write no resource at all, you should get a NOT_FOUND.

But we can not implement this for all ContentFormat because some Content Format encodes both exactly in the same way.

Eg. for SenML JSON

/3441/0/1110 :  { 3 = "newString"}

will be encoded in

 [{"n":"/3441/0/1110/3","vs":"newString"},

and

/3441/0/1110 :  { 3 = "newString"}
/3441/0/1120 :  { }

will also be encoded in :

 [{"n":"/3441/0/1110/3","vs":"newString"},

So I don't know if it is better to :