Things Gateway - the RESTful API and the Tide Light

In each of my previous postings about the Things Gateway from Mozilla, I've shown how to either attach an existing thing or create a new virtual thing.  Today, I'm going to talk about controlling things from outside the Things Gateway.

Nota Bene: The online service that provides tide data for this project no longer exists. You can never depend on a online service, even if you pay for it. The company that runs it (in this case, WeatherUnderground) may get purchased by another company (in this case, IBM) and they go and wreck everything. To get this project to work now, there would have to be a different source of daily tide information - this code was rather tightly coupled with the service it was using.

One of the most important aspects of Project Things is the concept of giving each IoT device a URL on the local area network.  This is includes the devices that natively cannot speak HTTP like all those Z-Wave & Zigbee lights and plugs.  The Things Gateway gives these devices a voice on your IP network.  That's a powerful idea.  It enables writing software that controls individual devices in a home using Web standards and Web tools.   Is the Things Gateway's rule system not quite sophisticated enough to accomplish what you want?  You can use any language capable of communicating with a RESTful API to control devices in your home.

My project today is to control the color of a Philips HUE bulb to tell me at a glance the phase and trend for the tide at the Pacific Coast west of my home.  When the tide is low, I want the light to be green.  When the tide is high, the light will be red.  During the transition from low to high, I want the light to slowly transition from green to yellow to orange to red.   For the transition from high tide to low tide, the light should go from red to magenta to blue to green.

So how do you tell a Philips HUE bulb to change its color?  It's done with an HTTP PUT command to the Things Gateway.  It's really pretty simple in any language.  Here's an asynchronous implementation in Python:

async with aiohttp.ClientSession() as session:
    async with async_timeout.timeout(seconds_for_timeout):
        async with session.put(
            "http://gateway.local/things/{}/properties/color".format(thing_id),
            headers={
                'Accept': 'application/json',
                'Authorization': 'Bearer {}'.format(things_gateway_auth_key),
                'Content-Type': 'application/json'
            },
            data='{{"color": "{}"}}'.format(a_color)
        ) as response:
            return await response.text()

Most of this code can be treated as boilerplate.  There are only three data items that come from outside: thing_id, things_gateway_auth_key, a_color.  The value of color is obvious, it's the color that you want to set in the Philips HUE bulb in the form a HEX string: '#FF0000' for red, '#FF00FF' for yellow, ...  The other two, thing_id and things_gateway_auth_key, are not obvious and you have do some mining in the Things Gateway to determine the appropriate values.

The Things Gateway will generate an authorization key for you by going to
≡ ⇒ Settings ⇒ Authorizations ⇒ Create New Local Authorization ⇒ Allow


You can even create authorizations that allow access only to specific things within your gateway.   Once you've pressed "Allow", the next screen gives you the Authorization Token as well as examples of its use in various languages:


Copy your Authorization Token to someplace that you can get reference to it again in the future.

The next task is to find the thing_id for the thing that you want to control.  For me, this was the Philips HUE light that I named "Tide Light".  The thing_id was the default name that the Things Gateway tried to give it when it was first paired.  If you didn't take note of that, you can fetch it again by using the command line Curl example from the example on the Local Token Service page shown above.  Unfortunately, that will return a rather dense block of unformatted json text.  I piped the output through json_pp and then into an editor to make it easier to search for my device called "Tide Light".  Once found, then I looked for the associated color property and found the href entry under the color property.
        
    $ curl -H "Authorization: Bearer XDZkRTVK2fLw...IVEMZiZ9Z" \
        -H "Accept: application/json" --insecure   \
        http://gateway.local/things | json_pp | vim -


        
    {
       "properties" : {
          "color" : { 
             "type" : "string",
            "href" : "/things/zb-0017880103415d70/properties/color"
            },
         "on" : {
             "type" : "boolean",
            "href" : "/things/zb-0017880103415d70/properties/on"
         }
         },
      "type" : "onOffColorLight",
      "name" : "Tide Light",
      "links" : [
          {
             "rel" : "properties",
            "href" : "/things/zb-0017880103415d70/properties"
            },
         {
             "href" : "/things/zb-0017880103415d70/actions",
            "rel" : "actions"
            },
         {
             "href" : "/things/zb-0017880103415d70/events",
            "rel" : "events"
            },
         {
             "rel" : "alternate",
            "href" : "/things/zb-0017880103415d70",
            "mediaType" : "text/html"
            },
         {
             "rel" : "alternate",
            "href" : "ws://gateway.local/things/zb-0017880103415d70"
         }
         ],
      "description" : "",
      "href" : "/things/zb-0017880103415d70",
      "actions" : {},
      "events" : {}
   }


Now that we can see how to get and change information on a device controlled by the Things Gateway, we can start having fun with it.  To run my code, the table below shows the prerequisites.


Requirements & Parts List:

Item What's it for? Where I got it
A Raspberry Pi running the Things Gateway with the associated hardware from Part 2 of this series. This is the base platform that we'll be adding onto From Part 2 of this series
DIGI XStick This allows the Raspberry Pi to talk the ZigBee protocol - there are several models, make sure you get the XU-Z11 model. The only place that I could find this was Mouser Electronics
Philips Hue White & Color Ambiance bulb This will be the Tide Light.  Set up one with a HUE Bridge with instructions from Part 4 of this series or independently from Part 5 of this series. Home Depot
Weather Underground developer account This is where the tide data comes from.  The developer account is free and you can get one directly from Weather Underground.
a computer with Python 3.6 My tide_light.py code was written with Python 3.6.  The  RPi that runs the Things Gateway has only 3.5.  To run my code, you'll need to either install 3.6 on the RPi or run the tide light on another machine. My workstation has Python 3.6 by default

Step 1: Install the software modules required to run tide_light.py:
        
    $ sudo pip3 install configman
    $ sudo pip3 install webthing
    $ git clone https://github.com/twobraids/pywot.git
    $ cd pywot
    $ export PYTHONPATH=$PYTHONPATH:$PWD
    $ cd demo
    $ cp tide_light_sample.ini tide_light.ini

Step 2: Recall that the Tide Light is to reflect the real time tide phase at some configurable location.  You need to select a location.  Weather Underground doesn't supply tide data for every location.  Unfortunately, I can't find a list of the locations for which they do supply information. You may have to do some trial and error.  I was lucky and found good information on my first try: Waldport, OR.

Edit the tide_light.ini file to reflect your selection of city & state, as well as your Weather Underground access key, the thing_id of your Philips HUE bulb, and the Things Gateway auth key:
        
    # the name of the city (use _ for spaces)
    city_name=INSERT CITY NAME HERE

    # the two letter state code
    state_code=INSERT STATE CODE HERE

    # the id of the color bulb to control
    thing_id=INSERT THING ID HERE

    # the api key to access the Things Gateway
    things_gateway_auth_key=INSERT THINGS GATEWAY AUTH KEY HERE

    # the api key to access Weather Underground data
    weather_underground_api_key=INSERT WEATHER UNDERGROUND KEY TOKEN HERE


Step 3: Run the tide light like this:
        
    $ ./tide_light.py --admin.conf=tide_light.ini


You can alway override the values in the ini file with command line switches:
        
    $ ./tide_light.py --admin.conf=tide_light.ini --city=crescent_city --state_code=CA


So how does the Tide Light actually work? Check out the source code. It starts with downloading tide tables in the manner shown in the code quote near the top of this page. The program takes the time of the next high/low tide cycle and divides it into 120 time increments. These increments correspond to the 120 colors in the low-to-high and high-to-low color tables. As each time increment passes, the next color is selected from the currently active color table.

Epilogue: I learned a lot about tides this week.  Having spent much of my life in the Rocky Mountains, I've never really had to pay attention to tides.  While I live in Oregon now, I just don't go to the coast that much. I didn't realize that tides were so variable.  I drove out to the coast to take photos of high and low tides to accompany this blog post, but surprisingly found that on average days the tides of the Oregon coast aren't all that dramatic.  In fact, my high and low tide photos from Nye Beach in Newport, OR were nearly indistinguishable.  My timing was poor, the tides are more interesting at the new moon and full moon times.  This week is not the right week for drama.   The photos that I published here are, for low tide, from May 17, 2017 and, for high tide, January 18, 2018.  The high tide photo was from an extreme event where a high tide and an offshore storm conspired for record-breaking waves.

low tide
high tide