In past tutorials, we have seen how to install Node-RED in Raspberry Pi, and People Counting Systems with OpenCV, Python, and Ubidots. This time, we'll learn how to provision devices and use them through balena to send data to Ubidots.

Balena is a powerful set of tools for building, deploying, and managing fleets of IoT devices. balena makes it easy to manage devices and their running services, to do so you can either go through their web dashboard or the API via the CLI and SDK. Balena allows you to choose the tools you want to use for your project so the platform adapts to your needs.

In this article, we will install and run a temperature sensor in a Raspberry Pi to send data to Ubidots using balena.

Requirements

Table Of Contents

  1. Setup Raspberry Pi 4 using balena

  2. Prepare your local computer to upload firmware changes using balena CLI

  3. Hardware setup

  4. Coding time

  5. Managing environmental variables in balena

  6. Results

1. Setup Raspberry Pi 4 using balena

Once you have created your balena account, your first step will be to create a fleet which are the settings that will go through a group of devices. In this case, we will create a fleet that will hold Raspberry Pi 4s.

Step 1: Click on the create fleet button in the left corner

Step 2: Fill in the requested information

Step 3: After having created the first fleet you can add a device. You'll have to select:

  • The device

  • The operating system

  • The version

  • The connection to the network. It can be through Ethernet-only or through Ethernet and Wi-Fi.

Step 3: Download balena Etcher

Step 4: To flash the firmware onto an SD card you have two options, either click on flash which will automatically open balena Etcher or you can download the balenaOS to a file. For reference, we used the first option.

Step 5: Select target

Step 6: Click on Flash!

NOTE: Make sure you change any firmware settings before mounting the SD card onto the Raspberry Pi.

  • For instance, we had to enable the SPI port before flashing the SD card, so the OneWire protocol would work for the Temperature sensor.

2. Prepare your local computer to upload firmware changes using balena CLI

The balena CLI is a Command Line Interface for balenaCloud or openBalena. You may follow these instructions to install it in your environment.

Step 1: Install the balena CLI, you can choose from macOS, Windows, and Linux

Step 2: Add the directory in which we downloaded the CLI into your path so that you can run the same commands from any directory.

Step 3: Login into the balena from the terminal. We recommend doing the web authorization as it's a really quick and straightforward process.

3. Hardware setup

Thankfully, there's the DS18B20 digital sensor, which supports the OneWire protocol, making it quite simple to plug into your Raspberry Pi. Here's the wiring diagram for your reference:

4. Coding time

Open your preferred code editor. We'll be using Visual Studio to edit the Docker file and the Python script that reads the temperature values and sends them to Ubidots.

Step 1: Specify which OS you'd like to install into your Raspberry Pi. You can search through balenas website which OS are available.

Step 2: Docker file

  • Withermsernsor will be for the Temperature sensor itself.

  • Requests will be to send data to Ubidots.

  • The third command tells the Raspberry Pi which directory we will be saving all the code.

  • The fourth command is to copy the code.

  • The fifth command enables the one wired protocol in the Raspberry Pi and finally executes the "main.py" script.

FROM balenalib/raspberrypi4-64-debian-python:3-bullseye
RUN pip3 install w1thermsensor requests
WORKDIR /app
COPY . .
CMD modprobe w1-gpio && modprobe w1-therm && python3 main.py

Step 3: Main.py

In this code you have two parts:

  • The first part reads the temperature from the sensor.

  • The second part sends the data to Ubidots.

Copy the following code and save it as main.py

from time import sleep
import os
import requests
from w1thermsensor import W1ThermSensor #We import the W1ThermSensor package

SLEEP = os.getenv("sleep")
DEVICE = os.getenv("device")
TOKEN = os.getenv("ubi_token")

BASE_URL = "https://industrial.api.ubidots.com"

REQUESTS_FUNCTIONS = {"get": requests.get, "post": requests.post}

def main():
sensor = W1ThermSensor() #Create the sensor object
while True:
temperature = sensor.get_temperature() #Obtains the temperature in Celsius
print(f"The temperature is {temperature} celsius") #Print the result
payload = build_payload("temperature",temperature)
print(f"[INFO] Payload to send: {payload}")
req = update_device(DEVICE, payload, TOKEN)
print(f"[INFO] Request result: {req.text}")
print({"status": "Ok", "result": req.json()})
sleep(int(SLEEP))
def build_payload(variable,value):
payload = {variable:value}
return payload

def update_device(device, payload, token):
"""
updates a variable with a single dot
"""
url = "{}/api/v1.6/devices/{}".format(BASE_URL, device)
headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
req = create_request(url, headers, payload, attempts=5, request_type="post")
return req

def create_request(url, headers, data, attempts, request_type):
"""
Function to create a request to the server
"""
request_func = REQUESTS_FUNCTIONS.get(request_type)
kwargs = {"url": url, "headers": headers}
if request_type == "post":
kwargs["json"] = data
try:
req = request_func(**kwargs)
print("[INFO] Request result: {}".format(req.text))
status_code = req.status_code
sleep(1)

​while status_code >= 400 and attempts < 5:
req = request_func(**kwargs)
print("[INFO] Request result: {}".format(req.text))
status_code = req.status_code
attempts += 1
sleep(1)
return req
except Exception as e:
print("[ERROR] There was an error with the request, details:")
print(e)
return None

if __name__ == "__main__":
main()

In this case, we will be using the OS library to get the environment variables and import them into the code, these environment variables can be set up through balena.

In this example, we created the following variables:

  • Sleep is the time interval between measurements.

  • Device is the label of the device that will be created in Ubidots

  • Token to authenticate HTTP requests sent from the device to the cloud.

Step 4: You need to add one line of code to the settings file to accept the one wired protocol. Go to the balena tutorial and copy the line and add it into the config TXT file of the flash of your SD card.

Step 5: Upload the code into balena: go to the directory where the code is saved and run the command balena push and the name of your fleet. For example, since the name of our fleet was "testingfleet", the command would be:

balena push testingfleet

You know that the code has been uploaded successfully once you see a unicorn.

5. Managing environmental variables in balena

One of the cool things about balena is the ability to set configuration parameters directly in the cloud, which makes it easy to manage a large fleet of devices remotely.

Step 1: Go to balena and click on your device name

Step 2: Select Device Variables

Step 3: Click on Add variable

Step 4: As mentioned above, we created 3 variables: token, device, and sleep.

  • For Sleep, we set 10 seconds between each loop

  • For the Device, we add its label: rpi4-balena

To get the Ubidots Token you need to go to your Ubidots account. Click on API credentials, copy the token, and past it in balena.

Once these variables have been set, balena will upload the newest version of the container into the Raspberry Pi including the changes of the variables that we just did.

6. Results

Step 1: Go to the devices menu at Ubidots. There you can find the new device,

now you can see the data that is being sent from balena to Ubidots.

Others also found useful:



Did this answer your question?