Web Thing Step-By Step

Why is it that when I switch a web-thing LED on and off, the request is PUT properties and not POST actions ???

This is what is sent to the things server when I toggle the LED:

PUT /things/led/properties/on

Interesting question. I had to search it and i found a very good explanation: https://www.keycdn.com/support/put-vs-post

@Novski - Thanks so much for helping, I looked at the link, but why is the gateway sending a PUT instead of a POST when I toggle the on/off switch ? - surely it should send a POST action and not a PUT property when changing the value of a property ?

Because the Staus (on/off) is known by the gateway it can replace it with the opposite.

If the State of the thing would not be known, then a Post is necessary to tell the thing to first check and then change it.

But the gateway should always know the state of a thing…

Hi @diginfo,

The gateway expects web things to follow the Web Thing API which means that the URL you enter should resolve to a Web Thing Description in JSON format (with a Content-Type: application/json header) which describes the web thing’s properties, actions and events.

The Web Thing REST API describes the RESTful API for communicating with a web thing. You can GET a property to read it and PUT a property to write it, or invoke an action with a POST for example. Setting a property is a PUT because it is overwriting the resource at the property URL with the payload of the request, whereas invoking an action is a POST because it’s create a new (action request) resource.

The specification says that “Actions are used when the setting of a property alone is not sufficient to affect a required change in state.”

I hope this helps.

2 Likes

Made a lot of progress with this on a custom nodejs web server and on MicroPython using my own web server ‘lite’ and have it working, with the exception of the “things” request.

For some reason, the system only recognises the second thing ‘GRN-13’ and never lists ‘RED-12’ as a thing that can be added:

  [
  {
    "name": "RED-12",
    "id": "RED-12",
    "@type": [
      "Light",
      "OnOffSwitch"
    ],
    "pin": 12,
    "@context": "https://iot.mozilla.org/schemas/",
    "description": "RED-12",
    "properties": {
      "on": {
        "href": "/things/RED-12/properties/on",
        "@type": "OnOffProperty",
        "type": "boolean",
        "value": false
      }
    }
  },
  {
    "name": "GRN-13",
    "id": "GRN-13",
    "@type": [
      "Light",
      "OnOffSwitch"
    ],
    "pin": 13,
    "@context": "https://iot.mozilla.org/schemas/",
    "description": "GRN-13",
    "properties": {
      "on": {
        "href": "/things/GRN-13/properties/on",
        "@type": "OnOffProperty",
        "type": "boolean",
        "value": false
      }
    }
  }
]

I can add the ‘GRN-13’ device and control it, but ‘RED-12’ is not listed and therefore cannot be added.

Any idea what is wrong ?

I thought that maybe it was because I did not include an “id”, however I added that into the definition and it makes no difference :frowning:

You can try adding your things individually. Click on “Add by URL…” on the screen where you add new things, then type http://<ip address>:<port>/things/RED-12, for instance.

Thanks, I can do that, but is this a bug with thing-url-adapter whereby it only parses the last thing in the things json array ??

I can manually add the device by URL and it works as expected, but it seems that the “title” property is needed as this is used by the discovery script to populate the input fields and thing’s name (or title) !

Also, I notice from the logs, that only one of the things is being polled (I have set poll freq to 15 seconds) every 15 seconds, the other device is not polled at all.

Hmm, interesting. I’ll look into this closer and will post back if I find something.

I’ve been doing some testing (using webthing-python) and I don’t have problems with discovering or polling multiple devices. Are you using webthing-upy or your own server implementation? It sounds like it may be your own.

Also, you need to add each of your things individually. Have you done that?

Yes I am using my own web server, see a few posts above where I show the JSON output from things: http://mydevice/

When none of the devices from my web server are added, and I press the + add devices, only the second thing is discovered (RED-12), I can then select the save button next to the discovered thing (RED-12) and add it, note that GRN-13 is not listed at all, the code cannot see GRN-13.

If I then re-run the discovery after adding the only available thing, nothing new is discovered, but I can manually add the second device (GRN-13) by URL http://192.168.0.186/things/GRN-13

I can then control both devices, and switch both on and off, but when I monitor the logs from my server, the Mozilla gateway is polling one of the devices TWICE (’/things/GRN-13/properties/on’) and no requests are ever received to poll RED-12, i.e 2 requests are received to poll ‘/things/GRN-13/properties/on’.

here is my things JSON again (http://192.168.0.186/):

[
  {
    "id": "http://192.168.0.186/things/RED-12",
    "properties": {
      "on": {
        "href": "/things/RED-12/properties/on",
        "@type": "OnOffProperty",
        "type": "boolean",
        "value": false
      }
    },
    "@context": "https://iot.mozilla.org/schemas/",
    "name": "RED-12",
    "description": "RED-12",
    "@type": [
      "Light",
      "OnOffSwitch"
    ],
    "title": "RED-12",
    "pin": 12
  },
  {
    "id": "http://192.168.0.186/things/GRN-13",
    "properties": {
      "on": {
        "href": "/things/GRN-13/properties/on",
        "@type": "OnOffProperty",
        "type": "boolean",
        "value": false
      }
    },
    "@context": "https://iot.mozilla.org/schemas/",
    "name": "GRN-13",
    "description": "GRN-13",
    "@type": [
      "Light",
      "OnOffSwitch"
    ],
    "title": "GRN-13",
    "pin": 13
  }
]

I have opened up the port to this device and sent you a personal message with the IP address and port.

Ok, so I see a couple of things that may be causing issues.

  1. Your server is responding with Content-Type: text/html.
  2. You should really includes a links array in your thing description and property descriptions. See the examples here. href is the old way of doing things.
  3. name is no longer used by the gateway, although that wouldn’t really cause issues. Ditto for pin.
  4. Your properties should probably include a title, and omit the value.

For discovery, how are you broadcasting your device via mDNS? What is the service type, what is the path, etc.?

Do you see any errors in your gateway log? Relevant items would be prefixed by thing-url:.

Thanks;

  1. My server will respond with whatever content type is requested using the Content-Type specified in the request header, so if you just use a browser then it will respond using text which the browser requested, if the request asks for JSON then it will reply with that instead.

  2. OK but given that resources are limited on MicroPython, I would prefer to only include what is essential.

3&4. pin and value are used by me and can be ignored by the gateway ?

I think discovery is done by the web-things plugin right ?? - doesn’t it make a http request to the url root to get a list of things ??

If you add this url to your own gateway setup, does it all work as expected ??

1 Like
  1. You should be looking at the Accept header on the request, which should be application/json. Please respond with that. Your server is working fine when responding to the add-on. It was only in my browser that it was responding as text/html.
  2. links should be considered essential, as href is no longer in the spec.
  3. Yes, those will be ignored by the gateway.
  4. title is used by the gateway, but value will not be.

The adapter discovers new devices via mDNS. See comment here. This is what makes things automatically appear in the new things list. So, if you want that to work, you need to broadcast as _webthing._tcp, with a path=/ TXT record.

And yes, if I add your IP address manually, things are working fine. If I watch things in Wireshark, I see both endpoints being polled separately.

EDIT: For an example of the mDNS bit, see here: https://github.com/mozilla-iot/webthing-upy/blob/master/webthing/server.py#L235-L241

By the way, your property values are both null.

mDNS is not available on the official esp8266 port (which I am running).

I have changed “href” to use the “links” array instead.

FYI, the hardware I am using is here: https://www.electrodragon.com/product/wifi-iot-relay-board-based-esp8266/ which is using esp-12 and IO12 and IO13 for the 2 on-board relays, and IO14 for the on-board DHTXX which is useless because of the heating effect of the on-board power supply :slight_smile:

By the way, your property values are both null .

Just fixed that

Another question, if devices are listed in the “+ add Thing” page that are only discovered by dns, why is it that one of my things is automatically listed and can be added from this page ?

The other, first device in the http://host/ JSON array is not shown and has to be added manually ?

You probably have one of the two configured in the add-on settings, i.e. in Settings -> Add-ons, then click Configure on the “Web Thing” add-on. That’s the only way they would show up without mDNS.

Things still appear to be working properly for me with your changes.

I misunderstood the purpose of the URLS added to “Configure thing-url-adapter” setup page.

I assumed that these were the server host addresses, and that the module would make a call to thee root (/) of each URL listed there to get a list of things that are hosted on that host.

So in the urls field I added the host IP address: http://192.168.0.186/ and by doing this, when you click the + on the tings page to discover new things, the module does query this page and returns the last item found in the JSON array for http://192.168.0.186/

I then added this item by clicking the save button, but as the other thing was not discovered I added that manually.

Then when I look at the server logs, the web things module does not poll both devices, but polls one device twice.

mDNS is not well supported on the official ports and querying the root of the server for a list of things on that server seems a much easier thing to do :slight_smile: