Post

RPi IoT Project - Temperature and Humidity with DHT11/22 & MongoDB

Raspberry IoT with MongoDB and Metabase

In this IoT Project we will be collecting Temperature and Humidity Data from a DHT11 or a DHT22 Sensor working together with a Raspberry Pi.

The data store will be in MongoDB, which will live in a Docker container.

Then, we will visualize the IoT data with Metabase.

Before Starting

HardwareCodeData Analytics Stack
Raspberry Pi 4PythonMongoDB
DHT11 or DHT22DockerfileMetabase
WiresDocker-compose StackDocker Container

Desktop View From DHT sensor to Metabase - Our Workflow

We can use Raspberry Pi 64 bits for this project. Or to run the Python script in a 32bits RPi and Official Mongo with Docker image in ARM64/X86. We can use unofficial apcheamitru/arm32v7-mongo image as well. For Metabase visualization, we need x86.

The Sensor: DHT11 or DHT22

Temperature and Humidity Data.

PinsDescription
+Connect 5V or 3.3V
dataTemp and Humidity data will be flowing here
-Ground (0V)

Connecting a DHT to a Raspberry Pi 4

To connect the sensor to the Raspberry, you can follow this schema:

Desktop View DHT22 connection to a Raspberry Pi 4

I prefer to use the 3.3V for the DHT22, and yet it will work perfectly with 5V as well.

In the RPi Official web you can find the original GPIO schema. You can always go to the terminal and check with:

1
pinout

Why MongoDB?

  • Scalability: MongoDB is a scalable database that can handle large amounts of data. This is important for IoT projects, which can generate a lot of data from sensors and devices.
  • Flexibility: MongoDB is a document-oriented database, which means that it is flexible and can store a variety of data types. This is important for IoT projects, which can generate data from a variety of sensors and devices.
  • Performance: MongoDB is a performant database that can handle high read and write volumes. This is important for IoT projects, which can generate a lot of data in real time.

To Do list

  • Send DHT Data to MongoDB
    • Hardware Check
    • Python Script
    • The Database: MongoDB

Python Script

We need to use the following libraries:

1
2
pip install Adafruit_DHT
pip show Adafruit_DHT

More About Adafruit_CircuitPython_DHT and in Github

We will be using the pymongo client to push the Data that Python reads from the Sensor to MongoDB.

1
2
pip install pymongo
#pip show pymongo
  • To Connect to our MongoDB server we are using:
1
2
mongo_client = pymongo.MongoClient("mongodb://localhost:27017/")
#replace with your server's connection details
  • Select the MongoDB database and collection you want to work with:
1
2
3
4
5
6
7
# Select a database
db = mongo_client["your_database_name"]

# Select a collection within the database
collection = db["your_collection_name"]

#  We will be using proper naming here
  • And we will insert data with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Define the data to insert (as a Python dictionary)
data_to_insert = {
       "field1": "value1",
       "field2": "value2",
      # Add more fields as needed
    }

# Insert the data into the collection
result = collection.insert_one(data_to_insert)

# Print the inserted document's ID
print(f"Inserted document ID: {result.inserted_id}")

#   Customize the `data_to_insert` dictionary with your data fields and values.

Here is the full Python Code ready for the container:

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
import Adafruit_DHT
import time
import os
from pymongo import MongoClient

DHT_SENSOR = Adafruit_DHT.DHT11 #example with DHT11, we can use DHT22 as well
DHT_PIN = 4

# Get MongoDB host from environment variable
mongodb_host = os.environ.get('MONGODB_HOST', 'localhost')  # Default to 'localhost' if not set

# Configure MongoDB connection
mongo_client = MongoClient(f'mongodb://{mongodb_host}:27017/')
db = mongo_client['sensor_data']
collection = db['dht_sensor']

while True:
    humidity, temperature = Adafruit_DHT.read(DHT_SENSOR, DHT_PIN)
    if humidity is not None and temperature is not None:
        data = {
            "timestamp": time.strftime('%Y-%m-%dT%H:%M:%SZ'),
            "temperature": temperature,
            "humidity": humidity
        }
        collection.insert_one(data)
        print("Data sent to MongoDB")
    else:
        print("Sensor failure. Check wiring.")
    time.sleep(3)

It is ready to detect the mongoDB configuration from our Docker-Compose stack. As well as the type of sensor that we are using DHT11 or DHT22.

Building the container

Let’s put that code inside a Docker container, so that the dependencies will be covered forever.

1
docker build -t dht_sensor_mongo .
  • Send DHT Data to MongoDB
    • Hardware Check
    • Python Script: and even inside a Docker container!
    • The Database: MongoDB

The DataBase: MongoDB

We will use the latest Docker image of MongoDB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
version: '3'
services:
  mongodb:
    image: mongo:latest
    container_name: mongodb
    environment:
      MONGO_INITDB_ROOT_USERNAME: yourusername
      MONGO_INITDB_ROOT_PASSWORD: yourpassword
    volumes:
      - mongodb_data:/data/db
    ports:
      - "27017:27017"
    restart: always

volumes:
  mongodb_data:

Start a new mongosh shell and check everything works:

1
2
3
4
5
6
7
8
9
docker exec -it mongodb sh #get inside mongo container

mongo -u yourusername -p yourpassword --authenticationDatabase admin #start MongoDB Shell with credentials
#mongosh --username yourusername --password yourpassword --authenticationDatabase admin

show dbs
use sensor_data
db.dht_sensor.find().sort({timestamp: -1}).limit(5)
#show collections

Quick Setup

We will be using the Docker-Compose Stack that consolidates the Python Code I have created, together with provisioning a MongoDB:

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
version: '3'
services:
  mongodb:
    image: mongo:latest
    container_name: mongodb
    environment:
      MONGO_INITDB_ROOT_USERNAME: yourusername
      MONGO_INITDB_ROOT_PASSWORD: yourpassword
      MONGO_INITDB_DATABASE: sensor_data
    volumes:
      - mongodb_data:/data/db
    ports:
      - "27017:27017"
    restart: always

  dht_sensor_mongo:
    image: dht_sensor_mongo:latest  # Use the name of your custom image
    container_name: dht_sensor_mongo
    privileged: true
    depends_on:
      - mongodb
    environment:
      MONGODB_HOST: mongodb
      MONGODB_PORT: 27017  # Specify the MongoDB port
      MONGO_INITDB_ROOT_USERNAME: yourusername  # Specify the MongoDB root username
      MONGO_INITDB_ROOT_PASSWORD: yourpassword  # Specify the MongoDB root password
      MONGO_DB_NAME: sensor_data  # Specify the MongoDB database name
      MONGO_COLLECTION_NAME: dht_sensor  # Specify the MongoDB collection name
      DHT_SENSOR_TYPE: DHT22  # Set the DHT sensor type here (DHT11 or DHT22)
      DHT_PIN: 4  # Set the DHT sensor pin here      

volumes:
  mongodb_data:
  • Send DHT Data to MongoDB
    • Hardware Check
    • Python Script
    • The Database Setup: MongoDB

Desktop View Sending Temp and Humidity data successfully from a Raspberry Pi 4 and DHT sensor to MongoDB

Metabase

What about the visualization? Let’s give it a try to Metabase

We can install it with Docker by using this configuration below:

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3'
services:
  metabase:
    image: metabase/metabase
    container_name: metabase
    ports:
      - "3000:3000"
    volumes:
      - metabase_data:/metabase-data
    restart: always

volumes:
  metabase_data:

Acces it at: http://localhost:3000

Desktop View Metabase Ready to Roll


FAQ

Useful MongoDB Shell commands

Some examples of MongoDB commands that you can run using the mongosh client:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# List all databases
show dbs

# Switch to the "my_database" database (it will create it if it does not exist) 
use sensor_data

# List all collections in the "sensor_data" database
show collections

# Create a new collection called "my_collection"
db.createCollection("my_collection")

# Insert a document into the "my_collection" collection
db.my_collection.insertOne({name: "John Doe", age: 30})

# Find documents in the "my_collection" collection
db.my_collection.find()

# You can check the the data is inserted on our future collection with
db.dht_sensor.find()

# And to get the latest ones
db.dht_sensor.find().sort({ timestamp: -1 }).limit(10);

How to embed a Metabase Dashboard?

Metabase provides an embedding code snippet that you can use to include a Metabase dashboard into your application. Here are the general steps to embed a Metabase dashboard:

  • First, create and configure the dashboard you want to embed within your Metabase instance.

  • Generate an Embedding Code:
    • Open the dashboard you want to embed.
    • Click on the “Share this dashboard” button (it looks like a share icon).
    • In the “Share Dashboard” dialog, click on the “Embed in another page” option.
    • Customize the settings for your embedded dashboard, such as the width, height, and whether to show the Metabase header.
    • Click the “Generate Embed Code” button.
  • Metabase will provide you with an HTML code snippet that you can use to embed the dashboard into your web application.
    • Copy the generated HTML code snippet and paste it into the HTML source code of your web application or webpage where you want the Metabase dashboard to appear.
1
2
3
4
5
6
7
<div>
  <iframe src="https://your-metabase-url/embed/dashboard/your-dashboard-id"
          width="800"
          height="600"
          frameborder="0"
          allowtransparency="true"></iframe>
</div>
  • Replace https://your-metabase-url with the URL of your Metabase instance and your-dashboard-id with the actual ID of the dashboard you want to embed.

  • Adjust Styling and Permissions: You may need to adjust the styling and permissions of the embedded iframe to match your application’s design and ensure that it’s accessible to your users.

Metabase and Satic Web Pages?

Yes, you can use the Metabase embedding feature in a Static Web Page.

The static webpage will remain static (yeah), and you can embed a Metabase dashboard within it. The embedded dashboard will be loaded dynamically into the static page, allowing you to display live data and visualizations without the need for server-side scripting.

To achieve this, follow the steps mentioned earlier to generate the embedding code from Metabase. You will receive an HTML code snippet that you can include in your static webpage’s source code.

Here’s a simplified example of how you can embed a Metabase dashboard in a static HTML page:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
    <title>My Static Webpage</title>
</head>
<body>
    <!-- Embed Metabase Dashboard -->
    <div>
        <iframe src="https://your-metabase-url/embed/dashboard/your-dashboard-id"
                width="800"
                height="600"
                frameborder="0"
                allowtransparency="true"></iframe>
    </div>

    <!-- Other static content goes here -->
</body>
</html>

Just include the iframe code generated by Metabase in your static HTML file where you want the dashboard to appear. When users access the static webpage, the embedded Metabase dashboard will be loaded and displayed within the page, while the rest of the content remains static.

This approach allows you to combine static content with dynamic Metabase dashboards, providing an interactive data visualization experience to your users within a static context.

Managing MongoDBs with UI - Mongo Express

Mongo Express allows us to interact with MongoDB database through the browser.

Installing Adafruit_DHT

More About Adafruit_DHT and in Github. Replaced with Adafruit_CircuitPython_DHT.

If you are getting problems to install the old Adafuit_DHT, you can try to do it from source:

1
2
3
4
5
git clone https://github.com/adafruit/Adafruit_Python_DHT.git
cd Adafruit_Python_DHT
python3 setup.py install --force-pi

#This will bypass any issues you may encounter when doing pip install Adafuit_DHT==1.4.0

Generally, you should just switch to the Adafruit DHT Circuit Python

Testing pymongo

With the latest pip version, you can try:

1
apt install python3-pymongo

Testing in Python venv

You can always test Python libraries in a virtual environment:

1
2
3
4
5
python3 -m venv my_virtual_env
source my_virtual_env/bin/activate

pip install Adafruit_DHT==1.4.0
#deactivate

Thanks to: https://pimylifeup.com/raspberry-pi-humidity-sensor-dht22/ for inspiration of this project.

And to: https://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/python-setup

This post is licensed under CC BY 4.0 by the author.