- From: Dom Guinard <dom@evrythng.com>
- Date: Fri, 05 Jun 2015 08:39:18 +0100
- To: Dave Raggett <dsr@w3.org>
- CC: Nick Allott <nick@nquiringminds.com>, David Janes <davidjanes@davidjanes.com>, Vlad Trifa <vladounet@gmail.com>, "public-web-of-." <public-web-of-things@w3.org>
- Message-ID: <55715226.8030809@evrythng.com>
Hi there, Following this discussion with great interest and while catching up with it I just wanted to clarify one thing: While CoAP requires a browser extension (if no CoAP to HTTP proxy is provided), MQTT does not require a browser extension as you can access MQTT over WebSockets in the browser (TCP for both). A widespread .js library to do this is available here: https://eclipse.org/paho/clients/js and you can test it for instance with the EVRYTHNG pub/sub broker: https://dashboard.evrythng.com/developers/apidoc/pubsub Dom > Dave Raggett <mailto:dsr@w3.org> > 4 June 2015 19:41 > Hi Nick, > > > For the WoT Framework, you would use a library, and I have a demo in > the NodeJS project[1]. You are limited by the same origin policy, > unless the server sets an appropriate CORS header. Another limitation > is to HTTP and Web Sockets, so you couldn’t use MQTT or CoAP without a > browser extension (see e.g. Copper on Firefox). This is indeed totally valid for CoAP which does require a browser extension. However MQTT does not. MQTT is TCP > > [1] https://github.com/w3c/web-of-things-framework > > Best regards, > — > Dave Raggett <dsr@w3.org <mailto:dsr@w3.org>> > > > > Dave Raggett <mailto:dsr@w3.org> > 4 June 2015 19:22 > Here’s my summary of the basics for using REST from my slides on the > WoT Framework > > Representational State Transfer (REST) > > * HTTP GET to retrieve a thing's description > * HTTP GET to retrieve *all* properties of a thing > * HTTP PUT to update *all* properties of a thing > * HTTP PATCH to apply changes to *some* properties > * HTTP POST to invoke actions on a thing > * HTTP POST is also used to notify events > o To proxies or dependent things > > REST can also be used with other protocols. > > These methods and their meaning are described in the HTTP specs, see > RFC 7231 and RFC 5789 for the PATCH method > > http://tools.ietf.org/html/rfc7231 > http://tools.ietf.org/html/rfc5789 > > In respect to using PATCH here is an extract from RFC 5789: > > > The URI paths are really a matter for each server. For the Web of > Things, we would like to decouple scripting from the protocols, as > this makes scripting easier, it allows the protocols to be changed as > requirements evolve, and it makes it easier to implement highly > scalable service platforms. As a result, developers only need to see > the URI for a thing’s description and won’t need to deal with the URIs > for the REST services described above. > > — > Dave Raggett <dsr@w3.org <mailto:dsr@w3.org>> > > > > David Janes <mailto:davidjanes@davidjanes.com> > 4 June 2015 17:53 > Yeah, I'm doing a brain dump / "strike when the iron is hot". > > (1) > I would say that there's no need to leave REST principles unless > there's some overwhelming benefit. It's what makes the web amazing, > and why we're not all using X.25 / SNA / NAPLPS / DECnet / Gopher or > whatever! > > (2) > > So ignoring istate / ostate and other stuff I'm pushing consider this > resource: > > http://mydoorlock.com/lock29/ > > which - for discussion sake - has two attributes: > > GET http://mydoorlock.com/lock29/ > { > lock: null, > is_locked: false > } > > So this tells me that the door is unlocked (is_locked), and there's no > one trying to lock it (lock). > > If I want to lock the door, I can just PATCH the resource > > PATCH http://mydoorlock.com/lock29/ > { > lock: true, > } > > Which if we GET the resource immediately (before the locking > completes, which involves a motor and time) we see the interstitial state: > > GET http://mydoorlock.com/lock29/ > { > lock: true, > is_locked: false > } > > And eventually the operation completes and we end up with this state > (the command attribute "lock" is always nulled when complete). > > GET http://mydoorlock.com/lock29/ > { > lock: null, > is_locked: true > } > > 3) > > No polling is required - we have lots of technologies for delivering > status updates asynchronously, MQTT, XMPP, AMQP, CoAP > > 4) > > So this does everything the POST model EVRYTHNG does, doesn't create > state on the on the server, can be observed by as many clients as we > want, doesn't create new resources to observer, is a Noun URL, and is > fully RESTful. > > D. > > > Vlad Trifa <mailto:vladounet@gmail.com> > 3 June 2015 22:44 > Hello, > > Active day on this list I see ;) > >> You're still using a verb (changestatus) in the URL. So this is >> non-RESTful. >> See anti-patterns on this page: >> http://www.restapitutorial.com/lessons/restfulresourcenaming.html > > Would you prefer .../actions/poolOfRequestsToChangeStatus/ instead? > This sounds much more RESTful to me, although a bit less pretty ;) > > >> 2) >> >> You've now created _another_ resource to be monitored - >> "http://mydoorlock.com/lock29/actions/changestatus/66373". When do >> you dispose of it? >> >> Note that this is another REST violation, as the server has to know >> that someone may be interested in what happened due to a request in >> the pass. It's not stateless: >> >> http://en.wikipedia.org/wiki/Representational_state_transfer#Stateless > > Hmmm... REST or not, the server doesn't care about clients indeed. > It's able to change its own resources when it wants! The server > decides how long to keep them, when to reset the counter, etc. So this > isn't anymore or less stateless than someone's bank account emptying > itself while he's not using his card (yeah, bills, etc.) > >> >> 3) >> >> How does a third party know that "http://mydoorlock.com/lock29/ >> <http://mydoorlock.com/lock29/actions/changestatus/66373>" is being >> manipulated at this time? Do I have to list what's at >> "http://mydoorlock.com/lock29/actions/changestatus >> <http://mydoorlock.com/lock29/actions/changestatus/66373>" and check >> every one of the children? If I only get a list of "active request" >> children, does the server have to remember I was interested in this >> in case I check back to see how they worked out? > > I don't see where why this is relevant in this context (why the > API/WoT standard should handle/specify). It feels to me this is an > issue of server policy/SLA (how you want to implement it), which I'm > not gonna get into. In server-based Web Things, what I put in a server > should be stored for ever, until I delete it (or until I stop paying > the bills). But on an embedded device, I can be ok with only having a > 1h buffer. So I don't think there's right or wrong here, and I'd > rather focus on how to handle the basics of how to interact with a > thing (which is the most important thing we need to agree on I think) > >> >> 4) >> >> Is this not RPC? Does not the resource >> "http://mydoorlock.com/lock29/actions/changestatus/66373" represent >> the end-to-end request, response, status of a particular action request? > > I'm not sure I understand this. It does indeed, but can you give me an > example of why/when this is a problem? > > Thanks! > > > >> >> D. >> >> >> On Wed, Jun 3, 2015 at 8:48 AM, Vlad Trifa <vladounet@gmail.com >> <mailto:vladounet@gmail.com>> wrote: >> >> Hey David, >> >> I partially agree with this. >> >> I'll rarely need to get the metadata of what properties & co are, >> so they obviously shouldn't be returned every time, and that's >> why you'd call the end-point below only once (to discover it and >> understand it). Then you'll only need to interact with >> ".../sensors/humidity" directly where you don't get that data >> model anymore - but just the definition. >> >> I'm not OK with the idea that any property and sensor MUST use >> JSON-LD. If we can all agree here on one basic model that is good >> enough and sufficiently flexible to deal with (yes, you are >> introducing some coupling, which you're doing with JSON-LD >> anyway, and even more so), then I don't need JSON-LD. >> >> But I'm obviously OK with the idea that any device can (and even >> should) expose its services with json-id so that it has more >> flexibility to expose metadata & co and more (non-wot) clients >> can also process it. >> >> >> Now, where I disagree is the "actions" model is RPC and >> non-RESTful. This is most likely because I didn't explain them >> well, so let's see: >> >> Doing a PUT .../actions/lockdoor is indeed non-RESTful (or worse: >> GET .../actions/lockdoor?lock=true ---> horrible, I know!!), >> because you're putting rpc semantics in the URL. That's bad! >> >> BUT, this is _not_ how actions work! >> >> When you do an action, you're creating a REST resource (so you >> MUST use POST), and this resource is a "request to do something" >> (that might happen or not). >> >> The way you'd unlock the door would look like this: >> >> POST http://mydoorlock.com/lock29/actions/changestatus >> { >> "status":"lock" >> } >> >> 202 ACCEPTED (or 201 CREATED, if instantaneous) >> Location: http://mydoorlock.com/lock29/actions/changestatus/66373 >> >> Then you can retrieve this resource any later time and see >> whether it's been successfully executed or not. This has the >> added advantage that you naturally have a buffer where different >> clients can schedule several requests simultaneously (and the >> device decides when & how to schedule those), which is >> particularly helpful, clean, and RESTful. >> I'll happily sit down and watch you demonstrate what's not >> RESTful about this ;) >> >> What do you think? >> >> >> Vlad >> >> >> >>> On 03 Jun 2015, at 00:50, David Janes <davidjanes@davidjanes.com >>> <mailto:davidjanes@davidjanes.com>> wrote: >>> >>> So just taking these as examples (make sure to add Accept: >>> application/json) >>> >>> http://devices.webofthings.io/pi/sensors/ >>> >>> "humidity": { >>> >>> "description": "A temperature sensor.", >>> >>> "frequency": 5000, >>> >>> "name": "Humidity Sensor", >>> >>> "timestamp": "2015-06-02T16:06:26.398Z", >>> >>> "type": "float", >>> >>> "unit": "percent", >>> >>> "value": 40.2 >>> >>> >>> }, >>> >>> From IOTDB's POV, there's a bunch of stuff being mixed together >>> here: >>> >>> The model, comprising the values: description, type, unit >>> The metadata, comprising the value: name, frequency >>> The ostate, comprising: timestamp, value >>> >>> In IOTDB world, the value record would look something like this: >>> >>> { >>> "@context": "...", >>> "value": 40.2, >>> "timestamp": "2015-06-02T16:06:26.398Z", >>> } >>> >>> @context is JSON-LD magic to provide meaning to "value" and >>> "timestamp", defined in the Model (@vocab may be needed too, >>> JSON-LD needs some tightening). >>> >>> The Model is then basically static, and the part that defines >>> value e.g. looks like this >>> >>> { >>> "@id": "#value", >>> "iot:unit": "iot:float", >>> "iot:purpose": "iot-attribute:sensor.humidity", >>> } >>> >>> A lot of those iot: can be taken out, but you get used to it. >>> >>> Metadata is less frequently changing data and is to taste, but >>> you'll note that the value will only reference the Model, not >>> the Metadata. Furthermore, Metadata will typically draw it's >>> definitions from the core vocab, rather than having to be >>> defined on a case by case basis. >>> >>> >>> D. >>> >>> >>> >> >> > > David Janes <mailto:davidjanes@davidjanes.com> > 3 June 2015 21:06 > __ REST / Actions __ (sorry, gmail won't let me change the Subject:) > > Thanks, I get what you're saying I'm pretty sure. > > 1) > > You're still using a verb (changestatus) in the URL. So this is > non-RESTful. > See anti-patterns on this page: > http://www.restapitutorial.com/lessons/restfulresourcenaming.html > > 2) > > You've now created _another_ resource to be monitored - > "http://mydoorlock.com/lock29/actions/changestatus/66373". When do you > dispose of it? > > Note that this is another REST violation, as the server has to know > that someone may be interested in what happened due to a request in > the pass. It's not stateless: > > http://en.wikipedia.org/wiki/Representational_state_transfer#Stateless > > 3) > > How does a third party know that "http://mydoorlock.com/lock29/ > <http://mydoorlock.com/lock29/actions/changestatus/66373>" is being > manipulated at this time? Do I have to list what's at > "http://mydoorlock.com/lock29/actions/changestatus > <http://mydoorlock.com/lock29/actions/changestatus/66373>" and check > every one of the children? If I only get a list of "active request" > children, does the server have to remember I was interested in this in > case I check back to see how they worked out? > > 4) > > Is this not RPC? Does not the resource > "http://mydoorlock.com/lock29/actions/changestatus/66373" represent > the end-to-end request, response, status of a particular action request? > > D. > > >
Received on Friday, 5 June 2015 07:39:56 UTC