Creating a REST web service with Python for serving TinkerForge sensor data in JSON

Creating a REST web service with Python for serving TinkerForge sensor data in JSON

This tutorial is demonstrating one solution to serve data read from TinkerForge sensors via a REST web service. It is implemented utilizing Python on a Fedora Unix (for ARM) running on a Cubietruck. It is not handling the basics of connecting to TinkerForge hardware, as this is covered quite well on their homepage.

About REST

REST is an acronym for “Representational State Transfer” and stands for a programmers paradigm mainly used in web applications. The main idea behind REST states, that one URL should present exactly one type of site content (independent where this content was generated from; e.g. a search on database). This behavior for static content (such as permalinks) is written down in the HTTP Internet standard. REST is based on five principles:

  1. Client – Server separation; server and client may be implemented independently, even in varying programming languages, when the interface between them is well-matched.
  2. Cacheable – All responses must be flagged as cacheable or not; when using cache headers in the responses with cache expired times this helps improving performance and scalability, as the client can respect this for further connections to the service.
  3. Stateless Transfer – this means that each individual request from a client to the service holds all necessary information to establish the connection (e.g. user data for authentication)
  4. Layered System – for a client it is not clear whether it is already connected to the end server or everywhere in-between (for instance: a load balancing system). This is also connected with the REST caching.
  5. Uniform interface – this means a decoupling of the architecture. An individual resource is identified in a request for instance using URIs. And the resources are conceptual separated from the representation that is send to the client. This means, a REST service may connect to a database based on a query that is invoked by the client connection, but will return not the database query back, but rather XML or JSON. For the client it is not visible how exactly the service is “working” in the background.

It is important to note, that REST itself is not a standard, like SOAP-based web services are. REST is meant to be an architectural style, whereas SOAP is a protocol. But REST is resting upon common Internet standards, like URI, HTTP or XML.

REST HTTP methods

URL (or resource) GET PUT POST DELETE
Collction URI:
http://myserver/weather/
List all URIs and maybe more details of collection members Replace the collection by another one Create a new collection member. The service will return the URI of the new member. Delete the full collection
Element URI, such as
http://myserver/weather/temperature
Retrieve a representation of this member including the data connected with the member in a format like JSON or XML. Create a new member or when it exists already, replace it. Most likely not used / implemented. Delete the specific member in the collection

Prerequisites

After some theory, let´s get started with the implementation. I assume, that you already installed python and „pip”, as well as the whole Tinkerforge SDK on your system.

If not already, install them:

To install the Tinkerforge SDK, please visit the webpage about their SDK for Python installation.

Let´s get started

There are multiple frameworks, like Django REST framework etc. available for Python, but I used Flask with mimerender as this combination seemed most flexible in their set-up for me. As just basic functionality regarding GET requests is needed for the implementation I decided against a complex framework like Django is.

To install Flask and mimerender, just call the following command from the command line:

After installation,  create a Python file that will include the source code for setting up a.) a rest web service b.) the connection to the Tinkerforge hardware.

First we need our parameters about the Tinkerforge hardware, like the UID of your Wireless Lan brick and the values for your HOST  and PORT. I prefer to use the Brickviewer to access those values.

In case you are ready to implement more than just the temperature service, you can also set-up and connect further devices. But this is not covered here.

To get the connection and the REST service working we need some imports, like the just intalled Flask and mimerender, but also JSON libs and the Tinkerforge libraries.

To set-up the app, we are defining special routes for specific URLs, like the root („/“) or our temperature REST service.

For instance, our service for serving the current temperature shall be available at /rest/v1.0/temperature/, a route for this URL is defined as follows:

The global variable currentTemperature is returned through the mimerender in the formats HTML, XML, JSON or as plain text, where you can define the output by yourself.  In this example above, the standard return will be in JSON.

The current value of currentTemperature is set by a callback function every 100ms:

As just explained, you have several channels than can be used to output the content. In my case, they are defined as follows:

The main function is capable of starting the IP connection to the Tinkerforge hardware, setting up the callback for reading the temperature value and for starting your REST service.

The IP connection to Tinkerforge hardware is established first with the HOST and PORT parameters set-up in the beginning of your script. After that the device object „t“ is created, calling the Temperature for the specific UID „U4“  through your IP connection.

With t.set_temperature_callback_period(time in ms) you can actual set the period for writing the temperature into the current temperature variable. In this case we call it every 100ms.

app.run(host=’192.168.1.144′, port=8080) will make your service available at the specific IP and Port. In my case a „0.0.0.0“ was not working as IP address, but it might be working for you.

Starting and testing your service

The service can be started from console and will list the full URL where it is available from. In the example below, the first connection to our designed URL returned the HTTP status code 200 and was delivering the content as defined before. As this connection was invoked from a web browser, the requested feedback was HTML.

In the following examples we are using curl to get the data back in different formats:

XML:

 JSON:

 HTML:

 

 

Full source code

Here is the full code example I implemented to get the whole service working:

 

 

 [/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]

Leave A Comment