Stand with Ukraine flag
Pricing Try it now
Edge
How to install ThingsBoard Edge on Raspberry Pi 4?
Getting Started Documentation Devices Library Installation Architecture API FAQ
On this page

How to install ThingsBoard Edge on Raspberry Pi 4?

Introduction

Raspberry Pi 4 Raspberry Pi has long been the gold standard for inexpensive single-board computing, powering everything from robots to smart home devices to digital kiosks. When it launched in 2019, the Raspberry Pi 4 took Pi to another level, with performance that’s good enough to use in a pinch as a desktop PC, plus the ability to output 4K video at 60 Hz or power dual monitors. More recently, the Raspberry Pi 4 (8GB) model came out, offering enough RAM for serious desktop computing, productivity and database hosting.

In this guide, you will learn how to install ThingsBoard Edge on a Raspberry Pi 4, create a device, install the required libraries and tools.
After this, we will modify our code and upload it to the device, and check the results of our coding and check data on ThingsBoard Edge using imported dashboard. The device will synchronize with ThingsBoard Edge using client and shared attributes requests functionality.
Additionally, you’ll learn how to control the device using platform features such as shared attributes and RPC requests.

Prerequisites

Before proceeding, ensure you have the following requirements in place:

Starting Edge on the Raspberry Pi 4

  • Log in to the ThingsBoard Community Edition instance and go to the Edge Management > Instances section. Click the “+” icon in the top right corner and select the “Add new edge” option.

  • Enter a name for your Edge in the “Name” field and click the “Add” button to confirm the addition of your new Edge.

  • Your new Edge should now appear at the top of the list, as entries are sorted by creation time by default.

To proceed with the Edge installation on the Raspberry Pi 4, you need to initiate an SSH (Secure Shell) connection.

For security reasons, SSH is disabled by default on all Raspberry Pi devices. You need to enable it to continue. If you have a monitor and keyboard connected, you can enable SSH during storage device setup, via the GUI, or in the Terminal.

To enable SSH in the Terminal, run:

1
sudo raspi-config

On the Raspberry Pi Software Configuration Tool (raspi-config) page:

  • Go to Interface Options and press Enter to select it.

  • Select the “Enable/disable remote command line access using SSH” option and press Enter.

  • Select Yes to confirm that the SSH server is to be enabled

  • A confirmation message should appear indicating that the SSH server is enabled.

  • Select Finish and close the program.

To initiate an SSH (Secure Shell) connection to the Raspberry Pi 4, open the Terminal and run the following command:

1
ssh pi@ip_address #Enter the actual IP address

ip_address: Replace “ip_address” with the actual IP address of the Raspberry Pi 4.
Password: The Terminal will request the password. The default password is raspberry.

Once connected, follow the installation instructions below. Start by creating a new directory:

1
mkdir tb_edge

Open this directory:

1
cd /home/pi/tb_edge

Create a docker compose file for the ThingsBoard Edge service within this directory:

1
nano docker-compose.yml

Then, you need to fill this file with the configuration lines. Once the Edge instance has been created, the preset installation instructions will be available for use. They contain important credentials, such as Edge Secret, Edge Key, etc. To access these configurations:

  • Go to the Edge management > Instances section of your ThingsBoard Community Edition instance, and click on the Instance. Then, click the “Install & Connect Instructions” button.

  • On the “Install & Connect Instructions” pop-up window, select the “Docker” tab and copy the configuration lines.

  • Paste the copied lines into the docker-compose.yml file and press CTRL+S to save it. To close the file press CTRL+X.

  • Execute the following commands:

1
2
docker compose up -d
docker compose logs -f mytbedge
Doc info icon

The command must be executed in the same directory in which the docker-compose.yml file was saved.

To set up a local port forwarding via SSH, open another terminal tab and run the following command:

1
ssh -N -L 8080:127.0.0.1:8080 pi@ip_address #Enter the actual IP address

Any connection to localhost:8080 on your local machine will be forwarded to 127.0.0.1:8080 on the Raspberry Pi 4.

The ThingsBoard Edge instance is available at http://127.0.0.1:8080. Use your credentials to log in.

Create device on ThingsBoard Edge

For simplicity, we will provide the device manually using the UI.

  • Log in to your ThingsBoard Edge instance and go to the Entities > Devices section. Click the “+” button in the top-right corner and select Add new device.

  • Enter a device name, for example, “My Device”. You can leave all other fields with their default values. Click Add to add the device.

  • Your first device has been added.

Install required libraries and tools

You should have installed thingsboard-python-client-sdk which can be installed using the following command. Still, we recommend installing packages outside the global environment:

1
pip3 install tb-mqtt-client

Also, you should have tools that allow editing code, for example, you can use Nano editor that is going out of the box or install any other code editor you are familiar with.

Connect device to ThingsBoard Edge

To connect your device, you’ll first need to get its credentials. While ThingsBoard Edge supports a variety of device credentials, for this guide, we will use the default auto-generated credentials, which is an access token.

  • Click on the device to open device details.

  • Click “Copy access token”. The token will be copied to your clipboard. Please save it in a safe place.

Now you are ready to publish telemetry data on behalf of your device. We will use, as mentioned before, the thingsboard-python-client-sdk library.

Let’s set up our project:

  1. Create project folder:

    1
    
    mkdir thingsboard_edge_example && cd thingsboard_edge_example
    
  2. Install packages:

    1
    
    pip3 install tb-mqtt-client
    
  3. Create the main script:

    1
    
    nano main.py
    
  4. Copy and paste the following code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    
    import logging.handlers
    import time
    import os
       
    from tb_gateway_mqtt import TBDeviceMqttClient
       
    ACCESS_TOKEN = "TEST_TOKEN" 
    THINGSBOARD_EDGE_SERVER = 'RPi_4_IP_ADDRESS' 
    
    logging.basicConfig(level=logging.DEBUG)
       
    client = None
       
    # default blinking period
    period = 1.0
       
       
    # callback function that will call when we will change value of our Shared Attribute
    def attribute_callback(result, _):
         print(result)
         # make sure that you paste YOUR shared attribute name
         period = result.get('blinkingPeriod', 1.0)
    
    # callback function that will call when we will send RPC
    def rpc_callback(id, request_body):
        # request body contains method and other parameters
        print(request_body)
        method = request_body.get('method')
        if method == 'getTelemetry':
            attributes, telemetry = get_data()
            client.send_attributes(attributes)
            client.send_telemetry(telemetry)
        else:
            print('Unknown method: ' + method)
       
       
    def get_data():
        cpu_usage = round(float(os.popen('''grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage }' ''').readline().replace('\n', '').replace(',', '.')), 2)
        ip_address = os.popen('''hostname -I''').readline().replace('\n', '').replace(',', '.')[:-1]
        mac_address = os.popen('''cat /sys/class/net/*/address''').readline().replace('\n', '').replace(',', '.')
        processes_count = os.popen('''ps -Al | grep -c bash''').readline().replace('\n', '').replace(',', '.')[:-1]
        swap_memory_usage = os.popen("free -m | grep Swap | awk '{print ($3/$2)*100}'").readline().replace('\n', '').replace(',', '.')[:-1]
        ram_usage = float(os.popen("free -m | grep Mem | awk '{print ($3/$2) * 100}'").readline().replace('\n', '').replace(',', '.')[:-1])
        st = os.statvfs('/')
        used = (st.f_blocks - st.f_bfree) * st.f_frsize
        boot_time = os.popen('uptime -p').read()[:-1]
        avg_load = (cpu_usage + ram_usage) / 2
       
        attributes = {
            'ip_address': ip_address,
            'macaddress': mac_address
        }
        telemetry = {
            'cpu_usage': cpu_usage,
            'processes_count': processes_count,
            'disk_usage': used,
            'RAM_usage': ram_usage,
            'swap_memory_usage': swap_memory_usage,
            'boot_time': boot_time,
            'avg_load': avg_load
        }
        print(attributes, telemetry)
        return attributes, telemetry
       
    # request attribute callback
    def sync_state(result, exception=None):
         global period
         if exception is not None:
             print("Exception: " + str(exception))
         else:
             period = result.get('shared', {'blinkingPeriod': 1.0})['blinkingPeriod']
    
    def main():
         global client 
         client = TBDeviceMqttClient(THINGSBOARD_EDGE_SERVER, username=ACCESS_TOKEN)
         client.connect()
         client.request_attributes(shared_keys=['blinkingPeriod'], callback=sync_state)
            
         # now attribute_callback will process shared attribute request from server
         sub_id_1 = client.subscribe_to_attribute("blinkingPeriod", attribute_callback)
         sub_id_2 = client.subscribe_to_all_attributes(attribute_callback)
    
         # now rpc_callback will process rpc requests from server
         client.set_server_side_rpc_request_handler(rpc_callback)
    
         while not client.stopped:
             attributes, telemetry = get_data()
             client.send_attributes(attributes)
             client.send_telemetry(telemetry)
             time.sleep(60)
       
    if __name__=='__main__':
        if ACCESS_TOKEN != "TEST_TOKEN":
            main()
        else:
            print("Please change the ACCESS_TOKEN variable to match your device access token and run script again.")
    

In the code above, change values for the following variables - THINGSBOARD_EDGE_SERVER, ACCESS_TOKEN to your credentials.

Necessary variables for connection:

Variable name Default value Description
ACCESS_TOKEN TEST_TOKEN Your device access token
THINGSBOARD_EDGE_SERVER RPi_4_IP_ADDRESS The IP address of your Raspberry Pi running Edge

If you are running the script on the same Raspberry Pi where Edge is installed, you can also use localhost.

  1. Click Ctrl+O and Ctrl+X keys to save the file.
  2. And finally, let’s start our script:

    1
    
    python3 main.py
    

If you did everything right, you should see the following console output:

1
2
3
4
5
> INFO:tb_device_mqtt:connection SUCCESS
> 
> 
> {'ip_address': '192.168.1.198', 'macaddress': '3c:06:30:44:e0:24'} {'cpu_usage': 6.6, 'processes_count': 8, 'disk_usage': 70.0, 'RAM_usage': 73.9, 'swap_memory_usage': 69.4, 'battery': 29, 'boot_time': 1675154176.0}
> 

Let’s review and make an explanation for our code. In this step, we are interested in the get_data function. Data packing and returning in the get_data function, so you can easily add new telemetry or attributes to the dictionary if you want to monitor more values:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
def get_data():
       cpu_usage = round(float(os.popen('''grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage }' ''').readline().replace('\n', '').replace(',', '.')), 2)
       ip_address = os.popen('''hostname -I''').readline().replace('\n', '').replace(',', '.')[:-1]
       mac_address = os.popen('''cat /sys/class/net/*/address''').readline().replace('\n', '').replace(',', '.')
       processes_count = os.popen('''ps -Al | grep -c bash''').readline().replace('\n', '').replace(',', '.')[:-1]
       swap_memory_usage = os.popen("free -m | grep Swap | awk '{print ($3/$2)*100}'").readline().replace('\n', '').replace(',', '.')[:-1]
       ram_usage = float(os.popen("free -m | grep Mem | awk '{print ($3/$2) * 100}'").readline().replace('\n', '').replace(',', '.')[:-1])
       st = os.statvfs('/')
       used = (st.f_blocks - st.f_bfree) * st.f_frsize
       boot_time = os.popen('uptime -p').read()[:-1]
       avg_load = (cpu_usage + ram_usage) / 2
   
       attributes = {
           'ip_address': ip_address,
           'macaddress': mac_address
       }
       telemetry = {
           'cpu_usage': cpu_usage,
           'processes_count': processes_count,
           'disk_usage': used,
           'RAM_usage': ram_usage,
           'swap_memory_usage': swap_memory_usage,
           'boot_time': boot_time,
           'avg_load': avg_load
       }
       print(attributes, telemetry)
       return attributes, telemetry
...

Send data part, as you can see below, we send our attributes and telemetry data every 60 seconds (feel free to change it if you want more frequent data updating):

1
2
3
4
5
6
7
...		
    while not client.stopped:
        attributes, telemetry = get_data()
        client.send_attributes(attributes)
        client.send_telemetry(telemetry)
        time.sleep(60)
...

Synchronize device state using client and shared attribute requests

Doc info icon

Make sure to create the shared attribute blinkingPeriod on your device.

The example code includes functionality to retrieve the device state from ThingsBoard Edge during boot. The relevant code sections are shown below.

Attribute callback:

1
2
3
4
5
6
def sync_state(result, exception=None):
    global period
    if exception is not None:
        print("Exception: " + str(exception))
    else:
        period = result.get('shared', {'blinkingPeriod': 1.0})['blinkingPeriod']

Attribute request:

1
2
3
4
5
def main():
    client = TBDeviceMqttClient("RPi_4_IP_ADDRESS", username="ACCESS_TOKEN")
    client.connect()
    client.request_attributes(shared_keys=['blinkingPeriod'], callback=sync_state)
    ...

In order for the callback to receive the shared attribute data from ThingsBoard Edge, the device must explicitly request it after connecting. This functionality allows the device to restore the correct attribute values after a reboot, preserving the actual state.

Check data on ThingsBoard Edge

After successfully publishing the attributes and telemetry, the data should appear right away in the “Latest telemetry” tab:

  • Click on the device to open the Device details page and select the “Latest telemetry” tab.

Let’s also display the single-board computer’s attributes and telemetry on a dashboard. To do this, you can either create your own dashboard using custom widgets or import a ready-made one.

Import dashboard

You are able to import a dashboard in JSON format. To import a dashboard, you should go to the Dashboard group and click the “+” button in the upper right corner of the page and choose “Import dashboard”. The dashboard import window should pop up, and you will be prompted to upload the JSON file and click “Import”.

Below, you can find the dashboard JSON file:

Check and control device data dashboard

After importing, we should choose an entity alias for our device.
To do this - we need to press the pen icon and select entity aliases, select alias “My device” and open it for editing by pressing the pen icon.
Then, choose a device with name My device from dropdown list and save entity alias. Now, you should be able to see the data from the device.

If you did everything right, you have to see the following dashboard: dashboard

Create a New Dashboard

We will create a dashboard and add the most popular widgets. See the instructions below.

  • Go to the Dashboards section. Click on the ”+” icon in the top right corner. Select “Create new dashboard”;

  • In the pop-up window, enter a dashboard title. Other fields are optional. Click the “Add” button to proceed;

  • After creating the dashboard, you will automatically transition to edit mode.

Add Entity Alias

Alias is a reference to a single entity or group of entities that are used in the widgets. An alias may be static or dynamic. We will use the ‘Single entity’ alias, referring to a single entity. In this case, ‘Raspberry Pi 4’. It is possible to configure an alias that references multiple devices. For example, devices of a certain type or related to a certain asset. You may learn more about different aliases here.

  • In the dashboard edit mode, click the “Entity aliases” icon in the top right corner.

  • Click “Add alias”.

  • Enter the alias name (for example, “My Device”). Select “Single entity” as the filter type and “Device” as the type. Then, select the device from the drop-down menu. Click the “Add” button.

  • Click “Save” to save the entity alias.

  • Finally, click “Save” on the dashboard editor page to save the changes. Then, re-enter edit mode.

To add the new widget, we need to select it from the widget library. The widgets are grouped into widget bundles. Each widget has a data source. It is how the widget “knows” what data to display. We should configure the data source to see the latest value of our “cpu_usage” data that we sent during step 2.

  • Enter the edit mode. Click the “Add new widget” button;
  • Select the “Charts” widget bundle. Click on the header of the Entities widget. The “Add Widget” window will appear;
  • Click “Add” to add the data source. A widget may have multiple data sources, but we will use only one;
  • Select the “Raspberry Pi 4” entity alias. Then click on the input field on the right. The auto-complete with available data points will appear. Select the “cpu_usage” data point and click “Add”;
  • To enlarge the widget by dragging its bottom right corner. Feel free to explore advanced settings for additional widget modifications.

Control device using shared attributes

Doc info icon

Don’t forget to create shared attribute blinkingPeriod on your device.

Also, we can change the period of the blinking using shared attribute update functionality.

This type of attribute is available only for Devices. It is similar to the Server-side attributes but has one important difference. The device firmware/application may request the value of the shared attribute(s) or subscribe to the updates of the attribute(s). The most common use case of shared attributes is to store device settings.

In order to run the code of this part of the guide, we recommend using Python 3.9 or above.

If you haven’t installed Python, please, follow the next steps:

1
2
sudo apt update
sudo apt install software-properties-common
1
sudo add-apt-repository ppa:deadsnakes/ppa
1
sudo apt install python3.9
1
sudo apt-get install -y python3 git python3-pip

Also, we will need Adafruit-Blinka library. Please, use the following command to install it:

1
pip3 install Adafruit-Blinka

For now, we are ready to write our code. In this part, we use new packages for blinking our LED in the blink function. Also, we use the attibute_callback function, which will be called when we change the value of our shared attribute. And finally, we bind our callback to subscriber in the main function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import digitalio
import board

...

# default blinking period
period = 1.0

# callback function that will call when we will change value of our Shared Attribute
def attribute_callback(client, result):
    print(client, result)
    # make sure that you paste YOUR shared attribute name
    period = result.get('blinkingPeriod', 1.0)

def main():
    ...
    # make sure that you paste YOUR shared attribute name
    sub_id_1 = client.subscribe_to_attribute("blinkingPeriod", attribute_callback)
    sub_id_2 = client.subscribe_to_all_attributes(attribute_callback)
    led = digitalio.DigitalInOut(board.PD14)
    led.direction = digitalio.Direction.OUTPUT
    ...
    led.value = True
    time.sleep(period)
    led.value = False
    time.sleep(period)

Also, if you are using the imported dashboard, you can change the blinking period using the following widget, which you can see in the bottom right corner of the dashboard:

attribute-update-widget

Control device using RPC

ThingsBoard Edge allows you to send Remote Procedure Calls (RPCs) from server-side applications to devices and vice versa. This feature enables you to send commands to/from devices and receive the results of command execution.

In this guide, we will configure an RPC command to get telemetry data from OrangePI immediately. If you are using the imported dashboard, there’s no need for additional configuration, as the dashboard already includes the following widget:

one-way-rpc-widget

💡 If you’re creating a new dashboard, you can use the “RPC Button” widget for one-way RPC communication, which is located in the “Control widgets” bundle.

Now, we are ready to write the code. First, create an rpc_callback function that will be triggered when the device receives an RPC request from the server. As in the example with shared attributes, we also need to bind our RPC callback function to the subscriber within the main function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
client = None

...

# callback function that will call when we will send RPC
def rpc_callback(id, request_body):
    # request body contains method and other parameters
    print(request_body)
    method = request_body.get('method')
    if method == 'getTelemetry':
        attributes, telemetry = get_data()
        client.send_attributes(attributes)
        client.send_telemetry(telemetry)
    else:
        print('Unknown method: ' + method)

...

def main():
    ...

    # now rpc_request_response will process rpc requests from server
    client.set_server_side_rpc_request_handler(rpc_callback)

    ...

When you click the RPC button, the device will immediately send telemetry (CPU %, Processes number, etc.). You can see this reflected in your dashboard, as shown in the chart below.

timeseries-rpc-widget

Also, if you did everything right, you should see the following console output:

1
{'method': 'getTelemetry', 'params': {}}

Conclusion

You can now easily install ThingsBoard Edge on the Raspberry Pi 4, connect your device, and begin sending data.

To go further, explore the ThingsBoard Edge documentation to learn more about key features, such as creating dashboards to visualize your telemetry, or setting up alarm rules to monitor device behavior in real time.