WebThingsIO / api

Web Thing API Specification
http://iot.mozilla.org/wot/
Other
164 stars 25 forks source link

Consider removing object wrapper from Property payload #143

Open benfrancis opened 4 years ago

benfrancis commented 4 years ago

Currently for a property definition in a Web Thing Description as below:

...
    "temperature": {
      "type": "number",
      "links": [{"href": "/things/pi/properties/temperature"}]
    }
...

a response to a GET request on the Property resource looks something like:

{
  "temperature": 21
}

where the payload is a JSON object with a map representation of the property's name and value. The payloads of PUT requests and responses also follow the same format.

@egekorkan has pointed out that if parsed as a W3C Thing Description using the latest W3C specification (assuming the links were parsed as forms) the default would be that the payload for the Property resource would just contain the value:

21

I believe the rationale for originally wrapping this as an object in the Mozilla specification was:

  1. In older versions of JSON an integer or string on its own would not be valid JSON, so it needed to be wrapped in an object.
  2. It helps with consistency for Properties resources and the setProperty and propertyUpdate WebSocket messages.

In order to move closer to the W3C specification we could consider removing this object wrapper for Property resources (which is now valid JSON). The Properties resource would still use a map for requests and responses, as is already the default for top level forms with readallproperties, writeallproperties, readmultipleproperties, or writemultipleproperties operations in the W3C spec.

Problems I can forsee with this are:

  1. This would be a backwards incompatible change which could cause breakage (we'd have to just live with that)
  2. Action, Event, Actions and Events resources all use similar wrappers and I'm not sure how we'd deal with those.
danielpeintner commented 4 years ago

In older versions of JSON an integer or string on its own would not be valid JSON, so it needed to be wrapped in an object.

I agree and confirm that the obsolete RFC 4627 is superseded by RFC 7159 which allows numbers, strings and such to be valid JSON.

Besides the existing rational I would like to add some more minor reasons why you might want to remove the wrapper.

However, I have to admit that I am certainly not fully aware of all the problems/consequences such a change might cause.

jtc42 commented 4 years ago

We're currently exploring a Web Things implementation designed for lab instrumentation, and have come up against this issue recently.

Our existing code works like the W3C spec and removes the object wrapper. We would, however, obviously prefer to be more compatible with Mozilla Web Things.

I'm realise such a massive change to the Mozilla spec is unlikely, but I'll follow this thread just in case. It'd be wonderful to have full compatibility, but as @danielpeintner said, I'm also not fully aware of the consiquences of such a change.

benfrancis commented 4 years ago

This has been playing on my mind too as I work on a greenfield web thing implementation and wonder whether to follow the Mozilla or W3C specification. I'd like to help converge the two but I don't think this change can be made to the Property resource in isolation, because Action and Event resources use the same object wrapper. It would also introduce inconsistency between the REST API and WebSocket API because the property name is still needed by the WebSocket API which lacks the additional context of Property resource URLs.

This is one issue I hope to address in the Web Thing Protocol Community Group so feel free to join that group if you are interested and I will try to get things kicked off at some point this year!!

jtc42 commented 4 years ago

Thanks! I've joined the community group now.

I agree that changing the Mozilla spec would have enough ramifications that it's likely infeasible, but I feel like the inconsistencies between the HTTP and WS APIs can be reconciled by treating the keys in the data object as an equivalent to the REST resource. The WS API wouldn't have to change for properties, and allows for batch property setters, for example:

{
  "messageType": "setProperty",
  "data": {
    "leftMotor": 100,
    "rightMotor": 200
  }
}

The REST equivalent would be a pair of requests, first to the leftMotor resource, with the body 100, then to the rightMotor resource, with the body 200

I do also agree that it doesn't make sense to change properties in isolation, but the same wrapper removal might also make sense for Actions especially, given that in the REST API the action name and input keys seem redundant given that the action name is in the resource URI, and the input is implied by sending a request body. In the WS API this would be:

{
  "messageType": "requestAction",
  "data": {
    "goForward": {
      "argument1": "value 1",
      "argument2": "value 2",
    },
  }
}

And for the REST API would be equivalent to a request to /actions/goForward with a request body:

{
  "argument1": "value 1",
  "argument2": "value 2",
}

I'm fumbling my way around the community group but hopefully there will be some kind of forum better suited for this discussion. I'm largely posting it here so it's out there before I forget...

danielpeintner commented 4 years ago

I am not sure if it helps but the only thing that needs to be clear is that Web Thing Descriptions and WoT TDs are not 100% the same.

Having said that, for example a Web Thing Description property

...
    "temperature": {
        "type": "number",
        "links": [{
            "href": "/things/pi/properties/temperature"
        }]
    }
...

maps to a WoT TD as follows.

...
    "temperature": {
        "type": "object",
        "properties": {
            "temperature": {
                "type": "number"
            }
        },
        "forms": [{
            "href": "/things/pi/properties/temperature"
        }]
    }
...

I believe there are other differences besides type and forms/links as well, am I wrong?

jtc42 commented 4 years ago

The only other difference I know of off the top of my head is that the W3C spec schema requires the @context to contain "https://www.w3.org/2019/wot/td/v1". It’s worth noting that the context given by default in Mozilla TDs is not truly valid for the W3C spec anyway as it resolves to a webpage, not a JSON-LD file. I don’t think the schema specifies this, but an online validator exists which gets unhappy if your context items don’t resolve to LD files.

benfrancis commented 4 years ago

I have started to document the differences between the Mozilla and W3C specifications here. Please feel free to edit the wiki page if you find any other differences that need addressing.

jtc42 commented 4 years ago

I have started to document the differences between the Mozilla and W3C specifications here. Please feel free to edit the wiki page if you find any other differences that need addressing.

This is super useful, thank you for writing it up!

I’m very new to following the W3C standardisation process, so am I right in thinking that the W3C TD spec is unlikely to change significantly now? I just wonder how prospective convergence is likely to work.

egekorkan commented 4 years ago

I right in thinking that the W3C TD spec is unlikely to change significantly now

Yes, this is correct :) The TD spec is in a maintenance round where a V1.1 will be introduced in 1-2 years (or maybe sooner) but will stay backward-compatible while adding some new features and fixing unclear or under-documented parts. This also means that if you want to propose new features, now is a good time ;)

benfrancis commented 4 years ago

I just wonder how prospective convergence is likely to work.

The hope of @mrstegeman and I is that the output of the Web Thing Protocol Community Group will fill in enough of the gaps (by defining a concrete sub-protocol for the Web of Things) that the Mozilla implementation will be able to migrate to that, and that if any changes are needed to the W3C Thing Description specification to make that work they should be quite minimal. I can't guarantee that the Mozilla implementation will ever support all W3C compliant Thing Descriptions (or all the features of Thing Descriptions) though, because IMO that's effectively impossible because of the way it is architected.

FYI I put out a call for Use Cases & Requirements for the Web Thing Protocol yesterday on the public mailing list and you can see a first draft to start the conversation here.

Another thing that might help is the W3C WoT Profiles work, which may make it possible to annotate a Thing Description to constrain it to using a particular (sub)-protocol. I am hoping to discuss that in the virtual face to face meeting today.

erkann-sen commented 4 years ago

Hi everyone,

There is one other thing, that differs in Mozilla WebThing Description from TD. The events usage in HTTP, in here events are explained as

"An Event Interaction Affordance describes an event source that pushes data asynchronously from the Thing to the Consumer."

But in Mozilla WebThing if an HTTP request to events URL is made. It returns the event history (not an event), synchronously, which should be a readOnly property not an event as logically.

So the only way it should work is in forms (or links in Mozilla), it should give a WebSocket link rather than an HTTP link.

By data types, there are 2 possibilities, 1-Change the return type from Object to value itself, or change the data type in Description as object and put the properties of objects correctly.

I am working, with this problem in my master thesis and created an hybrid approach, to tackle this problem with ease. By using node-wot library and an helper that I wrote, I can consume and use a Mozilla WebThing with a W3c consumer in here.

The helper;

benfrancis commented 4 years ago

"An Event Interaction Affordance describes an event source that pushes data asynchronously from the Thing to the Consumer."

This is quite off-topic now, but there are a couple of problems with that definition in the W3C specification IMO:

  1. HTTP doesn't have an established mechanism for pushing data asynchronously from a server to a client. Long-polling and Server Sent Events can both be used for this purpose, but the former is a bit of hack and the latter doesn't have good browser support.
  2. It's not very efficient to have a separate WebSocket connection for every affordance of a web thing, which is why the Mozilla specification points to a single WebSocket endpoint for each web thing in the top level links member rather than individual interaction affordances.

The Mozilla specification takes a pragmatic approach by using WebSockets to push event data to clients where possible and lets a client fall back to using HTTP GET requests to pull event data from the server when a WebSocket is not available.

The W3C specification does not specify a default mechanism for events (the HTTP Protocol Binding section doesn't mention events at all), so every web thing does it slightly differently.

I've added a note to the wiki page to say:

The Mozilla specification defines an Event resource for getting a log of instances of an event, an Events resource for getting a log of all events and a top level link to a WebSocket endpoint which can be used to push all types of events from the server to the client. By contrast the W3C specification defines a form for each event affordance, but does not specify a default mechanism for communicating event data.