Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How complicated can default mappings be? #407

Open
benfrancis opened this issue Feb 11, 2025 · 3 comments
Open

How complicated can default mappings be? #407

benfrancis opened this issue Feb 11, 2025 · 3 comments
Labels

Comments

@benfrancis
Copy link
Member

A key question that's on my mind when thinking about the relationship between Profiles and Protocol Binding Templates is how complicated default mappings inside a Binding Template can be, and at what point a default mapping becomes a sub-protocol.

We seem to have a tentative agreement around the idea that the Protocol Binding sections of Profiles don't really belong in Profiles and their content should be moved to individual binding documents as defaults instead. Those bindings and defaults can then be referenced as constraints in Profiles. E.g. The HTTP Basic Profile would assert that conforming Things must use the HTTP Binding Template and stick to its default mappings, and must use the JSON Payload Binding Template.

However, in order for this to work the default mappings in Binding Templates may have to become much more complicated than they are today. Currently almost all of the "default mappings" in existing binding documents map an operation to a single term in a binding vocabulary. E.g.:

  • readproperty -> "htv:methodName": "GET"
  • invokeaction -> "cov:method": "POST"
  • subscribeevent -> "mqv:controlPacket": "subscribe"
  • readallproperties -> "modv:function": "readHoldingRegisters"
  • observeproperty -> "bacv:usesService": "SubscribeCOV"

The protocol binding sections in Profiles are much more comprehensive than this and are written as a collection of assertions, e.g.

In order to read the value of a property, a Consumer MUST send an HTTP request to a Web Thing with:

  • Method set to GET
  • URL set to the URL of the Property resource
  • Accept header set to application/json

If a Web Thing receives an HTTP request following the format above and the Consumer has permission to read the corresponding property, then upon successfully reading the value of the property it MUST send an HTTP response with:

  • Status code set to 200
  • Content-Type header set to application/json
  • A body with the value of the property serialized in JSON

These assertions specify protocols, sub-protocols, methods, headers, response codes, payload bindings and in some cases even dynamic resources with fixed data schemas (ActionStatus). Profiles also constrain things like units, date formats and error formats - but those could be specified separately from binding documents.

As we all know by this point, the protocol bindings related to actions are of particular concern, because there are certain things that are currently very difficult or impossible to describe declaratively in a Thing Description. I know a lot of people think we should only set defaults for things that can be overridden using a binding vocabulary, which is where this gets tricky.

For example, in the HTTP Binding Template:

  • An invokeaction operation can have an htv:methodName of POST, but what should the response data schema look like if the action has not completed by the time the HTTP response is sent? Should the response contain a link or redirect to another resource which represents the action status?
  • What should the default mapping be for a queryaction operation, given there's currently no way to specify a separate data schema for result of a queryaction operation or dynamic resources in a Thing Description. A queryaction operation can have an htv:methodName of GET, but what URL does it act upon and what is the data schema of the response?
  • A cancelaction operation could have htv:methodName set to DELETE, but what resource does it act on if there's no way to specify dynamic resources?
  • A queryallactions operation could have a htv:methodName set to GET, but what should the data schema of the response look like?
  • In the default mapping of the readmultipleproperties operation, how should a Consumer specify which properties to read?
  • What should the default mapping be for observeproperty and subscribeevent operations? Should it use longpoll as a subprotocol? Or should these pub/sub style operations be separately defined in other binding templates like an HTTP SSE Binding Template and HTTP Webhook Template?

In some cases it may also be difficult to separate the protocol binding from the payload binding, e.g. The Server-Sent Events protocol binding is tightly coupled with the text/event-stream payload format.

So my key questions are:

  • How complicated can default mappings be?
    • Can they only be expressed as a table mapping operation names to vocabulary terms?
    • Can they be expressed as assertions?
    • What can those assertions constrain?
    • Can assertions constrain things which are currently difficult or impossible to override in a TD using vocabularly terms?
  • At what point does a default mapping become a sub-protocol?
    • Should the action queue binding from Profiles be a sub-protocol instead?
    • Would the whole of the protocol binding from the HTTP Basic Profile be better as a subprotocol instead?
@egekorkan
Copy link
Contributor

I think that this is a valid question but I think that I do not see a fundamental issue with bindings vs profiles. The main constraints you are highlighting comes from the lack of expressivity in the TD spec regarding async actions and meta operations. One point to highlight as a lack of binding is the SSE and/or WebHook. We definitely need it. I am not sure about WebHook though as it flips Thing and Consumer roles in relationship to Server/Client.

In some cases it may also be difficult to separate the protocol binding from the payload binding, e.g. The Server-Sent Events protocol binding is tightly coupled with the text/event-stream payload format.

We had a discussion about this in node-wot and we think that the form should contain application/json if the data within the text is actually json (see eclipse-thingweb/node-wot#1338). The presence of subprotocol:sse already implies that. There was a somewhat similar discussion with BACnet, which constrains the media type or Modbus which is just bytes.

How complicated can default mappings be?

We don't have an agreement so far but so far they are just operation to vocabulary term mappings. We can evaluate based on the examples/use cases but the answer to Can assertions constrain things which are currently difficult or impossible to override in a TD using vocabularly terms? is so far no. Those would not be defaults in my opinion.

@benfrancis
Copy link
Member Author

@egekorkan wrote:

The main constraints you are highlighting comes from the lack of expressivity in the TD spec regarding async actions and meta operations.

I agree, I'm just worried about whether the necessary level of expressivity will ever be reached.

One point to highlight as a lack of binding is the SSE and/or WebHook. We definitely need it. I am not sure about WebHook though as it flips Thing and Consumer roles in relationship to Server/Client.

I agree an HTTP SSE Binding Template would be useful, and I would be happy to contribute to that.

We had a discussion about this in node-wot and we think that the form should contain application/json if the data within the text is actually json (see eclipse-thingweb/node-wot#1338). The presence of subprotocol:sse already implies that.

I guess that makes sense and neatly sidesteps the need to describe a nested content type.

We don't have an agreement so far but so far they are just operation to vocabulary term mappings.

OK, so from my Web of Things (WoT) HTTP Protocol Binding 2.0 strawman proposal, only the blue tables would be allowed? All that can be specified in those tables is HTTP methods and headers, and if the protocol binding and payload binding are to be separated the Accept and Content-type headers would have to be removed from the protocol binding template (I'm not actually sure how profiles would require the presence of those headers). So that basically just leaves the HTTP method again.

Maybe by relying on the URI scheme to map to a protocol binding template and separating out the protocol binding and payload binding means a lot of the remaining content will drop out, but I still think that misses a lot of detail about how to interoperate.

I notice the current HTTP Binding Template vocabulary doesn't even include a term to describe a response code, even though the WoT Discovery specification uses the term htv:statusCodeValue.

Have there been any more proposals about how to describe dynamic resources?

I note that the issue about a lack of a data schema for queryaction has been "parked".

the answer to Can assertions constrain things which are currently difficult or impossible to override in a TD using vocabularly terms? is so far no. Those would not be defaults in my opinion.

FWIW I agree it's not a default if it can't be overridden, I'm just not confident that a sufficiently expressive vocabulary to override every little detail needed for out-of-the-box interoperability is going to arrive any time soon.

@benfrancis
Copy link
Member Author

Have there been any more proposals about how to describe dynamic resources?

See also: #408

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants