- 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