DEV Community

bjyurkovich
bjyurkovich

Posted on • Edited on

Get started with your IoT devices using iotery.io

Iotery is a managed IoT (Internet of Things) service that was born out of the need to eliminate the complexities of configuring and deploying with the various IoT cloud players of today: AWS IoT, GCP Core IoT, Azure IoT. Iotery attempts to provide developers a way to get their IoT devices connected to the cloud in under 15 minutes. This tutorial aims to provide you with an example to get started in 15 minutes.

What you will need for this tutorial:

  1. Raspberry Pi (not required, but will be cooler!)
  2. Basic knowledge of Python
  3. Basic knowledge on how to set up and connect to your Raspberry Pi

Setting up an Iotery Account

Iotery gives a generous free tier that allows up to 5 devices for free for life. For most hobbyists, this should be more than enough! Setting up a free account is easy: https://dashboard.iotery.io.

Iotery splits different environments into what they call teams. For this tutorial, we will just be using a single team called speedy-fast - you will want to create your own name.

If you are doing production-ready stuff - you will want to create two teams - one for production and one for testing.

Once we have our team, we are presented with an initial screen to create a Device Type. Before we speed off on doing something, let's make a quick plan.

Let's make a plan

Let's say we want to set up a device (a "thing") to report a temperature every 5 minutes to the cloud. Let's also have our device report the temperature when we send it a command.

Here's a simple diagram of what we will be doing:

Configuring Iotery for our Temperature Sensor

We need to do four things in the Iotery dashboard to get ready to report data to the cloud:

  1. Create our temperature sensor Device Type
  2. Create our temperature sensor Device
  3. Create our temperature Data Type
  4. Create a Command Type

Creating the Device Type

We need to set up Iotery to allow our Raspberry Pi to report. Since our Raspberry Pi is acting as a (really beefy) temperature sensor, we will create a device type in Iotery Dashboard called Temperature Sensor. All devices that are temperature sensors will be derived from this device type (for our purposes, we will only need one device - our Raspberry Pi!).

We can also just use the REST API to create a device type.

Creating the Device

Next, we need to create a device. You can set the serial, key, and secret to whatever you want - this is how you give your device its identity. We will use this later to authenticate our Raspberry Pi with Iotery.

Just like the device type creation, we can also just the REST API to create our device. Oh, there is also a JavaScript Node.js SDK!

The choice of secret is yours - just make sure to keep it secret! In this tutorial, we have opted to use BASIC authentication, so we will just use the serial, key, and secret to authenticated. Also make sure to set the Device Type to the Temperature Sensor device type we created previously.

If you want to be even more secure, you can use the KEYED option and use X.509 certificates for cryptographically signed authentication with Iotery.

Creating Data Types

In order to report data to the cloud, we need to tell Iotery what type of data to expect. In this case, we will be reporting a temperature, so we need to make a Temperature data type and assign it to our Temperature Sensor device type.

Once we create it, make a note of the enum you chose to name it. This will be used in the data packet when we send data up (it is not case sensitive!).

You can use the REST API to do this too!

We will set up the command later - let's get our temperature sensor (Raspberry Pi) reporting to the cloud!

Setting up our Raspberry Pi Temperature Sensor

The code and project below can be found here.

Since we now have Iotery set up with our temperature sensor identity, we can get to coding our Raspberry Pi. Iotery provides an embedded Python SDK to make life easier connecting our devices to the cloud! Let's set up our project.

If you need help setting up your Raspberry Pi, there are a number of tutorials on the web. Make sure to install Python 3. Here is an example tutorial to install Python 3 on your pi. If you do not have a Raspberry Pi, that's okay - you can do this on your laptop...you just won't be able to report a real temperature.

Logging into our Raspberry Pi on the command line, we will create a folder in our home directory and cd into it:

mkdir iotery-temperature-sensor
cd iotery-temperature-sensor

Once in the folder, we will create a virtual environment, making sure to use python3 as the primary interpreter:

virtualenv -p python3 venv

and we will activate the virtualenv:

source venv/bin/activate

You will know if it worked if there is a little (venv) at the beginning of your terminal line.

In the activated virtual environment, we will install the iotery-embedded-python-sdk:

pip install iotery-embedded-python-sdk

We are ready to start coding our sensor!

Sensor Code

To start, let's create a file main.py in our iotery-temperature-sensor folder that will be our sensor application file:

touch main.py

Open main.py in your favorite Python IDE (we like VSCode) and get to coding:

from iotery_embedded_python_sdk import Iotery

# team ID found on the dashboard: https://iotery.io/system
TEAM_ID="188baf45-8d55-11e9-c121-d283610663ed" 
iotery = Iotery()
d = iotery.getDeviceTokenBasic(data={"key": "temp-sensor-key",
                                     "serial": "temp-sensor-1", "secret": "my-secret", "teamUuid": TEAM_ID})

# set token for subsequent iotery calls
iotery.set_token(d["token"])

# get info about the device
me = iotery.getMe()

print(me["name"])

In this code snippet, we instantiate the Iotery class, then call getDeviceTokenBasic, passing in the identity that we created on the iotery dashboard for the device. Once we authenticated with Iotery, we got a token back, that we can use for other calls, like getMe().

Don't forget to replace the TEAM_ID with the ID of your team (see the System page on the dashboard) as well as my-secret with the secret that you used when creating the device.

Great! We are now connected with Iotery. When you run the code above, you should see the name of your device temp-sensor-1 printed to the console.

Reading temperature

We are going to create a helper function to read the Raspberry Pi's CPU temperature (unfortunately, the Pi does not come with a built in temperature sensor). In a new file called read_temperature.py, we write

import os
import random

# we checking for a real Pi - this code will also work on your computer
real_pi = True
try:
    import RPi.GPIO as GPIO
    real_pi = True
except:
    real_pi = False

def current_cpu_temperature():
    # gets the current CPU temperature of the Pi
    if real_pi:
        temp = os.popen("/opt/vc/bin/vcgencmd measure_temp").readline()
        temp = temp.replace("temp=","")
        temp = temp.replace("'C","")
        return float(temp)
    else:
        return 50 + int(random.random()*100)/100

and now we can add it to our main.py with a loop that reports our temperature data every 5 minutes.

from iotery_embedded_python_sdk import Iotery
from read_temperature import current_cpu_temperature
from time import sleep


# team ID found on the dashboard: https://iotery.io/system
TEAM_ID="188baf45-8d55-11e9-c121-d283610663ed" 
iotery = Iotery()
d = iotery.getDeviceTokenBasic(data={"key": "temp-sensor-key",
                                     "serial": "temp-sensor-1", "secret": "my-secret", "teamUuid": TEAM_ID})

# set token for subsequent eatery calls
iotery.set_token(d["token"])

# get info about the device
me = iotery.getMe()

print(me["name"])

while True:
    t = iotery.getCurrentTimestamp()
    temp = current_cpu_temperature()

    # https://iotery.io/docs/embedded/#tag/Embedded/paths/%7E1embedded%7E1devices%7E1:deviceUuid%7E1data/post
    data = {"packets":[{
        "timestamp": t,
        "deviceUuid": me["uuid"],
        "deviceTypeUuid": me["deviceTypeUuid"],
        "data":{"temperature": temp}
    }]}
    iotery.postData(deviceUuid=me["uuid"], data=data)
    sleep(60 * 5) # sleeps for 60 * 5 seconds (5 min)

We've added a few lines of code to main.py. The primary addition are the new import dependencies (first few lines), and the while True loop, which will run forever.

That loop simply gets the current timestamp from the Iotery server (you could also use the local time if you wanted with int(time.time())), gets the current temperature from our function we created, then posts the data to Iotery, and then sleeps for 5 minutes.

If you check out your device page in the dashboard, you can see the last time your device reported in the Live Data section.

Great, we are reporting to the cloud, and we still have some time left to set up our device to respond to a command to report!

Setting up Commands for our Temperature Sensor

We would like to be able to request the temperature any time from our Pi, so we need to send it a command. Just like before, we must tell Iotery what command types we will be sending. We just need one command: REPORT_TEMPERATURE.

But how do we get our Pi to listen for the command? We can use MQTT. Simply put, MQTT allows our devices to remain in constant contact with Iotery and get real-time data (including commands). Iotery provides a fully managed MQTT broker that we can have our Pi connect to and receive commands.

We will use a Python MQTT library to connect to Iotery's broker. Let's install it in the same folder as our application code (make sure you are still in your virtual environment!):

pip install paho-mqtt

and let's add the necessary code to main.py

from iotery_embedded_python_sdk import Iotery
from read_temperature import current_cpu_temperature
from time import sleep, time
import paho.mqtt.client as mqtt
import ssl


# team ID found on the dashboard: https://iotery.io/system
TEAM_ID="188baf45-8d55-11e9-c121-d283610663ed" 
iotery = Iotery()
d = iotery.getDeviceTokenBasic(data={"key": "temp-sensor-key",
                                     "serial": "temp-sensor-1", "secret": "my-secret", "teamUuid": TEAM_ID})

# set token for subsequent eatery calls
iotery.set_token(d["token"])

# get info about the device
me = iotery.getMe()

#  Set up the MQTT stuff
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))

    #once connected, subscribe to the command topic
    client.subscribe("devices/" + me["uuid"] + "/commands")


# The callback for when something is published to the broker.
def on_message(client, userdata, msg):
    print("Received from topic" + msg.topic)
    print("Message: " + str(msg.payload))

    if msg.topic == "devices/" + me["uuid"] + "/commands":
        # There is only one command for now, so we will just report.  If we add more later, we can look at the `commandTypeEnum` to control actions
        t = iotery.getCurrentTimestamp()
        temp = current_cpu_temperature()
        # https://iotery.io/docs/embedded/#tag/Embedded/paths/%7E1embedded%7E1devices%7E1:deviceUuid%7E1data/post
        data = {"packets":[{
            "timestamp": t,
            "deviceUuid": me["uuid"],
            "deviceTypeUuid": me["deviceTypeUuid"],
            "data":{"temperature": temp}
        }]}
        iotery.postData(deviceUuid=me["uuid"], data=data)
        print("data posted!")

client_id = TEAM_ID + ":" + str(iotery.getCurrentTimestamp()*1000) + ":" + me["uuid"] #Iotery client ID format
client = mqtt.Client(client_id)
client.on_connect = on_connect # set the connect handler to run when mqtt connects
client.on_message = on_message # the function that runs when we get a message

# username and password are your device's uuid and it's token we got back from auth above
client.username_pw_set(me["uuid"], password=d["token"])

# To use MQTTS (secure MQTT), we need to configure TLS
client.tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
    tls_version=ssl.PROTOCOL_TLS, ciphers=None) 

#  connect to the broker
client.connect("mqtt.iotery.io", port=8885, keepalive=60)

client.loop_start() # make sure to start the mqtt loop!

# the main application loop!
while True:
    t = iotery.getCurrentTimestamp()
    temp = current_cpu_temperature()

    # https://iotery.io/docs/embedded/#tag/Embedded/paths/%7E1embedded%7E1devices%7E1:deviceUuid%7E1data/post
    data = {"packets":[{
        "timestamp": t,
        "deviceUuid": me["uuid"],
        "deviceTypeUuid": me["deviceTypeUuid"],
        "data":{"temperature": temp}
    }]}
    iotery.postData(deviceUuid=me["uuid"], data=data)
    sleep(60 * 5) # sleeps for 60 * 5 seconds (5 min)

We added a lot of code functionality! Let's go through the additions one by one.

Add the necessary imports

We need to add the necessary libraries.

from iotery_embedded_python_sdk import Iotery
from read_temperature import current_cpu_temperature
from time import sleep, time
import paho.mqtt.client as mqtt
import ssl

We added the MQTT library paho.mqtt.client and ssl. We need ssl to use Iotery's secure MQTT option (MQTTS, MQTT over TLS).

MQTT callbacks

The MQTT library we are leveraging uses interrupts, so we must provide functions to handle the cases when our application connects to the broker, as well as when a message comes in.

#  Set up the MQTT stuff
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))

    #once connected, subscribe to the command topic
    client.subscribe("devices/" + me["uuid"] + "/commands")


# The callback for when something is published to the broker.
def on_message(client, userdata, msg):
    print("Received from topic" + msg.topic)
    print("Message: " + str(msg.payload))

    if msg.topic == "devices/" + me["uuid"] + "/commands":
        # There is only one command for now, so we will just report.  If we add more later, we can look at the `commandTypeEnum` to control actions
        t = iotery.getCurrentTimestamp()
        temp = current_cpu_temperature()
        # https://iotery.io/docs/embedded/#tag/Embedded/paths/%7E1embedded%7E1devices%7E1:deviceUuid%7E1data/post
        data = {"packets":[{
            "timestamp": t,
            "deviceUuid": me["uuid"],
            "deviceTypeUuid": me["deviceTypeUuid"],
            "data":{"temperature": temp}
        }]}
        iotery.postData(deviceUuid=me["uuid"], data=data)
        print("data posted!")

For simplicity of this tutorial, we have not set the command as executed. In a real application, we will want to notify Iotery that our device has set our command executed or with the python SDK: iotery.setCommandInstanceAsExecuted(deviceUuid=me["uuid"], commandInstanceUuid=command_from_broker["uuid"])

The on_connect callback handler runs when our Pi connects to the broker. MQTT has a publish/subscription model, where a client (our Pi) must subscribe to topics. We want to subscribe to the command topic for our device so we get commands when we send them: client.subscribe("devices/" + me["uuid"] + "/commands").

MQTT set up and connection to broker

We need to provide the appropriate address for the broker along with our credentials.

client_id = TEAM_ID + ":" + str(iotery.getCurrentTimestamp()*1000) + ":" + me["uuid"] #Iotery client ID format
client = mqtt.Client(client_id)
client.on_connect = on_connect # set the connect handler to run when mqtt connects
client.on_message = on_message # the function that runs when we get a message

# username and password are your device's uuid and it's token we got back from auth above
client.username_pw_set(me["uuid"], password=d["token"])

# To use MQTTS (secure MQTT), we need to configure TLS
client.tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
    tls_version=ssl.PROTOCOL_TLS, ciphers=None) 

#  connect to the broker
client.connect("mqtt.iotery.io", port=8885, keepalive=60)

The client_id must be in a specific format in order to connect to the broker. You will will also notice that we have opted to use MQTTS (MQTT over TLS) that encrypts all our data while in transit. We must tell the MQTT library that we are doing this with our client.tls_set(...) function.

Starting the MQTT loop

The library we are using is threaded, so we must tell our application to start the loop (before our while True directive):

client.loop_start()

Sending the Command

Now that we have a working connection with the broker, we are almost done! We just need to send the command now. We can do this in the Iotery Dashboard by viewing the Device we want to command (in our case, our Pi).

As soon as you send the command, you should see our Pi print out the command message and a data posted! string to the terminal.

You can also use the REST API to send the command from your cloud or consumer mobile app that you build.

Wrapping up

If you made it to this point, nice work (you get extra points if you did in 15 minutes)! We now have a Raspberry Pi (or your computer) connected to the cloud reporting data. If you implemented the MQTT communication, you can also send it real-time commands!

We have just brushed the surface of Iotery with this example. Iotery also provides the ability to:

  1. Create Device Networks where only one of the devices acts as a gateway
  2. Create Device Groupings
  3. Create schedules for your devices and commands
  4. Create notifications and alerts with severity and priority
  5. Manage firmware
  6. Use webhooks to create value-added applications with the Account Manager API that allows you to connect your own apps and manage your own experience without being locked-in with ballooning infrastructure costs.
  7. Use webhooks to train your own AI models and analytics!

...and much more.

Top comments (0)