Things Gateway - Series 2, Episode 1

In my previous seven part posting on the Things Gateway from Mozilla, I explored the various built in options for connecting with existing home automation technologies.  While interesting, at that point, the Things Gateway hadn't really broken any new ground.  The features could be found in other Home Automation projects, arguably in more mature environments.

With the release of version of 0.4, the Things Gateway introduces something entirely new that the other products in the field don't yet do. Mozilla is thinking about the Internet of Things in a different way: a way that plays directly to the company's strengths. What if all these home automation devices, switches, plugs, bulbs, spoke a protocol that already exists and is cross platform, cross language and fully open: the Web protocols.  Imagine if each plug or bulb would respond to HTTP requests as if it were a Web app.  You could just use a browser to control them: no need for proprietary software stacks and phone apps.  This could be revolutionary.

In this, the beginning of Series Two of my blog posts about the Things Gateway, I'm going to show how to use the Things Framework to create virtual Web things.

Right now, the Mozilla team on this project is focused intensely on making the Web Things Framework easy to implement by hardware manufacturers.  Targeting the Maker Movement, the team is pushing to make it easy to enable small Arduino and similar tiny computers to speak the Web of Things (WoT) protocol.  They've created libraries and modules in various languages that implement the Things Framework: Javascript, Java, Python 3 have been written, with C++ and Rust on the horizon.

I'm going to focus on the Python implementation of the Things Framework.  It is pip installable with this command on a Linux machine:
        $ sudo pip3 install webthing

The webthing-python github repo provides some programming examples on how to use the module.

One of the first things that a Python programmer is going to notice about this module is that it closely tracks the structure of a reference implementation. That reference implementation is written in Javascript. As such, it imposes a rather Javascript style and structure onto the Python API. For some that can roll with the punches, this is not a problem, for others, like myself, I'd rather have a more Pythonic API to deal with. So I've wrapped the webthing module with my own pywot (python Web of Things) module.

pywot paves over some of the awkward syntax exposed in the Python webthing implementation and offers some services that further reduce the amount code it takes to create a Web thing.

For example, I don't have one of those fancy home weather stations in my yard.  However, I can make a virtual weather station that fetches data from Weather Underground with the complete set of current conditions for my community.  Since I can access a RESTful API from Weather Underground in a Python program, I can wrap that API as a Web Thing.  The Thing Gateway then sees it as a device on the network and integrates it into the UI as a sensor for multiple values.

Weather Underground offers a software developers license that will allows up to 500 API calls per day at no cost.  All you have to do is sign up and they'll give you an API key.  Embed that key in a URL and you can fetch data from just about any weather station on their network.  The license agreement says that if you publicly post data from their network, you must provide attribution. However, this application of their data is totally private.  Of course, it could be argued that turning your porch light blue when Weather Underground says the temperature is cold may be considered a public display of WU data.

There is really very little programming that needs to be done to make a Web Thing this way.  Error handling and configuration boilerplate (omitted here) outweigh the actual code that defines my Virtual Weather Station:
class WeatherStation(WoTThing):

    async def get_weather_data(self):
        async with aiohttp.ClientSession() as session:
            async with async_timeout.timeout(config.seconds_for_timeout):
                async with session.get(config.target_url) as response:
                    self.weather_data = json.loads(await response.text())
        self.temperature = self.weather_data['current_observation']['temp_f']
        self.wind_speed = self.weather_data['current_observation']['wind_mph']
   
    temperature = WoTThing.wot_property(
        'temperature',
        initial_value=0.0,
        description='the temperature in ℉',
        value_source_fn=get_weather_data,
        units=''
    ) 
    wind_speed = WoTThing.wot_property(
        'wind speed',
        initial_value=0.0,
        description='the wind speed in MPH',
        units='MPH'
    ) 

The ability to change the status of devices in my home based on the weather is very useful.  I could turn off the irrigation system if there's been enough rain. I could have a light give warning if frost is going to endanger my garden. I could have a light tell me that it is windy enough to go fly a kite.



Is the wind calm or is it perfect kite flying weather?

If you want to jump right in, you can see the full code in my pywot git hub repo.  The demo directory has several examples.  However, in my next posting, I'm going to explain the virtual weather station in detail.

A few words about security: As I said before the Things Gateway and Things Framework are experimental software.  They are not yet hardened enough for more than experimental use.  Under no circumstances should a Web Thing be exposed directly to the Internet - they are for trusted local network use only.  Standards for authentication and authorization have not yet been engineered into the product.  They are in the works, hopefully by the next iteration, version 0.5.

From Ben Francis of the Mozilla ET IoT team: ...currently our Things Framework implementation assumes that a Things Gateway is used to expose those things to the Internet, where the gateway provides authentication, authorisation and encryption. This means that locally there is currently no authentication and while HTTPS support is provided, it can only really be used with self-signed certificates on a local network. We're not satisfied with that level of security and are exploring ways to provide authentication (in discussions with the W3C WoT Interest Group) and a solution for HTTPS on local networks (via the HTTPS in Local Network Community Group https://www.w3.org/community/httpslocal/). This means that for the time being we would strongly recommend against exposing native web things directly to the Internet using the direct integration pattern unless some form of authentication is used.