September 5, 2017 at 12:29 pm
We have developed a Python 3 library for communication with Turris Gadgets. It’s easy to use and provides great flexibility to create complex applications for Internet of Things. The library allows complete control over Turris Gadgets devices including their management, requesting their states, adding listeners to the events invoked by them, etc.
In the recent weeks, we have been working on several projects dealing with IoT and voice assistants like Amazon Alexa or Google Assistant. Our general target was the ability to control smart home devices by voice with these assistants. A simple diagram shows the basic principle:Several IoT devices are connected to a local server, in this case, Raspberry Pi 3. The server then communicates with an AWS Lambda service using MQTT protocol. AWS Lambda provides a way to access many different Amazon services. On the left of the diagram is Amazon Echo, which is used to provide voice input to AWS Lambda, which forwards the request to our local server using the MQTT protocol. The next simplified diagram shows the local server principle that we wanted to implement:
The local server does all the hard work, parsing requests coming either from Amazon, from the devices themselves (like pressing a button) or from other scripts and applications. One significant advantage of such layout is the fact that the system keeps working even when one of the controllers fails. For example, when the connection to the Internet is not available, you could still control the devices manually using mechanical buttons, etc. Automated and scheduled tasks would still work too. As can be seen, the primary communication protocol for IoT devices is MQTT. In the real world, there is a problem; not all IoT devices handle the MQTT interface. That’s why some protocol translator is needed. Our translator is a library converts the MQTT to other manufacturer specific protocols.
One of such groups of devices that we wanted to use for our projects is Turris Gadgets. For those who don’t know, Turris Gadgets is a joined CZ.NIC and Jablotron Group activity. The project aims to create a smart home network using the Turris router. The Turris Gadgets set contains several sensors, such as PIR motion detectors, shock detectors, etc. It also includes actuators like remote controlled outlets, relays, and a wireless siren. All of these sensors and actuators use a manufacturer’s proprietary wireless communication protocol. Jablotron provides a dongle with a radio, which plugs into the Turris router USB. With this and a little bit of software installed on the router, we can set-up a smart home very quickly.
You can find some open source solutions supporting Turris Gadgets. They usually are ready-made applications for complete home automation and connecting them to our application would present too much of a hassle. Also, the communication protocol used by the Turris Gadgets is rather simple and developing an interface for them is pretty straightforward. That’s why we decided to create our library to communicate with them.
We have chosen to implement the library in Python. The development was very convenient and fast. The main control program APIs that we used in our project were written in Python too. The library is elementary and starting the communication with the devices requires just a few lines of code.
import jablotron.events as events import jablotron.devices as devices dongle = devices.Dongle(port="/dev/ttyUSB0") dongle.init() def blink(event): for i in range(3): dongle.req_send_state(pgx="0") time.sleep(0.5) dongle.req_send_state(pgx="1") time.sleep(0.5) events.bind(events.Event.ev_PIR_motion, blink)
This simple example demonstrates just how easy it is to work with the library. First, we import the necessary sub-modules, and then we create the dongle instance, which opens a serial port and starts the transmitting and receiving threads. Then we call dongle.init(), which fetches all the information that the dongle has in its memory, which means that we get all registered peripherals. Let’s define an example function. This function just turns on and off an outlet three times in a row, which is done by calling dongle.req_send_state(), which broadcasts a state message to all registered devices. In the message, we can specify the required states of the outlets, alarm, beeper, etc. Finally, we bind this function to the event called ev_PIR_motion, which is an event that is triggered when any of the PIR sensors detects motion. The event object that is passed to the function contains an information about the time of the event occurrence, exact ID of the PIR sensor and other useful information. As can be seen, the library provides a simple way to incorporate the Turris Gadgets in any IoT project. Moreover, it offers great flexibility for controlling the devices. It’s also easy to register new peripherals to the dongle’s memory or delete them.
In the future, we will further improve the functionality of the library and add new features like keeping track of the old state of every device or storing the dongle’s memory in a file, so it’s not needed to fetch it on every start of the application. Stay tuned we will soon show how to use the Alexa and Google home to take advantage of this library.