Practice Lab Guide

Project 6: Cloud-Connected IoT Dashboard

Publish telemetry directly from ESP32 to the ThingSpeak Cloud database and write a Python analyzer to process history logs.
Domain
Cloud Databases & Visualization
Difficulty
⭐⭐⭐⭐☆ (Advanced)
Course Module
Cloud & Data Management
Deliverables
Cloud Dashboard Graphs, Python Query Script
1. Cloud Telemetry Data Pipeline Architecture

To enable historical data analysis and remote visualization, we establish a direct cloud data pipeline. The architecture below details the end-to-end telemetry path. The ESP32 reads physical environmental sensors (DHT22 and LDR) and initiates an HTTP connection to the ThingSpeak cloud REST API. Data is structured as parameters in an HTTP GET request. The ThingSpeak database stores this time-series data, updating its dashboard line graphs. A Python script running in VirtualBox queries the Read API via JSON to analyze peak temperature values.

ESP32 Client Node Read DHT22 (Temp) Read LDR (Light) HTTP GET Request Port 80 / No SSL THINGSPEAK CLOUD Write API (/update) Updates fields 1 & 2 Time-Series DB 24-hour log cache Read API (/feeds.json) JSON feed responses Python Client query_telemetry.py requests.get() JSON Parse loop Calculates max(temp)
2. Part 1: Step-by-Step Individual Commands & Dashboard Configuration GUI Steps

Follow these detailed steps to build the telemetry dashboard in ThingSpeak, set up your Python virtual environment inside the Ubuntu VM, install HTTP dependencies, and execute the analysis query.

STEP 1

Configure Dashboard Widgets in ThingSpeak Cloud

Open your ThingSpeak channel and configure the visual dashboard layout to display incoming sensor telemetry data.

ThingSpeak GUI Configuration: 1. Open your web browser and navigate to https://thingspeak.com 2. Sign in to your account, click "Channels" -> "My Channels" in the top menu, and click on your "IoT Telemetry" channel. 3. Click the "Add Widget" button in the Private View tab. 4. Select "Gauge" from the list of widgets, and click "Next". 5. In the configuration dialog, set: - Name: "Ambient Temperature" - Field: Field 1 (Temperature) - Min: 0, Max: 50 - Display Units: °C 6. Click "Create". 7. Click the "Add Widget" button again, select "Numeric Display", and click "Next". 8. Set: - Name: "Light Intensity" - Field: Field 2 (Light) 9. Click "Create". Drag and drop the widgets to organize your dashboard layout.
We configure visual widgets in the ThingSpeak dashboard to display real-time sensor metrics alongside historical line charts for ambient temperature and light intensity.
STEP 2

Launch VM Terminal and Create Dashboard Workspace

Boot up your VirtualBox Ubuntu machine. Open the terminal (Ctrl+Alt+T) and create a directory to organize your telemetry query scripts.

ubuntu@iot-vm:~$ mkdir -p ~/workspace/cloud_dashboard && cd ~/workspace/cloud_dashboard
We run `mkdir -p` and `cd` to generate and enter a dedicated workspace directory named `~/workspace/cloud_dashboard` to isolate our Python telemetry query script.
STEP 3

Install Python Requests Module inside the Virtual Environment

Create an isolated virtual environment and install the Requests library, which you will use to fetch JSON data from the ThingSpeak API.

ubuntu@iot-vm:~/workspace/cloud_dashboard$ python3 -m venv env && source env/bin/activate && pip install requests
We initialize the Python virtual environment and install the `requests` library. This module simplifies making HTTP calls to fetch raw JSON telemetry data from ThingSpeak's feeds API.
STEP 4

Create the Python Telemetry Query Script

Open the graphical text editor in the background to write the serial listener script.

(env) ubuntu@iot-vm:~/workspace/cloud_dashboard$ gedit query_telemetry.py &
We invoke `gedit` alongside the `&` symbol to open the graphical text editor in a background thread, leaving our terminal terminal prompt active for running commands.
STEP 5

Configure API Keys in the ESP32 Firmware

Edit the firmware variables in the Arduino IDE to match your home Wi-Fi credentials and your ThingSpeak Channel Write API Key.

Firmware Settings (Arduino IDE): 1. In the Arduino IDE sketch editor, locate the variables "ssid" and "password". Replace them with your local router credentials. 2. Locate the "apiKey" string variable. 3. Paste your ThingSpeak channel's "Write API Key" (found under the API Keys tab in ThingSpeak) inside the quotes. 4. Click the circular Upload arrow icon in the toolbar to upload the code to the ESP32.
We configure Wi-Fi credentials and the Write API Key in the firmware to ensure the ESP32 can connect to your local network and post sensor telemetry data to your ThingSpeak channel.
STEP 6

Run the Python Query Script to Analyze Telemetry Data

Run the query script in the VM terminal. The script will fetch the last 100 entries from the API and calculate the peak temperature value.

(env) ubuntu@iot-vm:~/workspace/cloud_dashboard$ python3 query_telemetry.py
We execute the Python query script, starting the loop that fetches the channel's JSON data feeds from ThingSpeak and calculates the maximum temperature value.
3. ThingSpeak Dashboard Widget Layout Grid

The visual arrangement of dashboard widgets in the web interface is organized in a responsive grid. The layout diagram below represents the grid organization showing how gauges, displays, and historical line charts are positioned.

Temperature Trend (Line Chart) Light Level Trend (Line Chart) Live Temperature (Gauge Widget) 24.5 °C Light Intensity (Numeric Widget) 1024 ADC Raw Range (0 - 4095)
4. Part 2: Complete Codebases & Line-by-Line Breakdowns

Below is the complete C++ firmware code to run on the ESP32, followed by the complete Python query script to execute inside your VirtualBox Linux VM.

Asset 1: ESP32 HTTP Client Firmware (`http_client.ino`)

Line-by-Line Code Breakdown

// Practice Project 6: ESP32 HTTP Client Firmware Code #include <WiFi.h> #include <HTTPClient.h> // Network Credentials & Channel Keys const char* ssid = "YOUR_WIFI_SSID"; const char* password = "YOUR_WIFI_PASSWORD"; const char* host = "api.thingspeak.com"; String apiKey = "YOUR_WRITE_API_KEY"; // Replace with your ThingSpeak Write API Key float dummyTemp = 24.5; int dummyLight = 800; void setup() { Serial.begin(115200); delay(10); // Connect to Wi-Fi Serial.print("Connecting to Wi-Fi SSID: "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWi-Fi connection established. IP Address: "); Serial.println(WiFi.localIP()); } void loop() { if (WiFi.status() == WL_CONNECTED) { WiFiClient client; HTTPClient http; // Simulate sensor variations dummyTemp += ((float)random(-30, 30) / 100.0); dummyLight += random(-15, 15); // Construct target API update URL String url = "http://" + String(host) + "/update?api_key=" + apiKey + "&field1=" + String(dummyTemp, 2) + "&field2=" + String(dummyLight); Serial.print("Sending HTTP request to URL: "); Serial.println(url); // Begin HTTP session http.begin(client, url); // Send GET request int httpResponseCode = http.GET(); if (httpResponseCode > 0) { String payload = http.getString(); Serial.print("HTTP Response Code: "); Serial.println(httpResponseCode); Serial.print("Entry Number Count: "); Serial.println(payload); } else { Serial.print("Error: HTTP request failed, code: "); Serial.println(httpResponseCode); } // Terminate HTTP session http.end(); } else { Serial.println("Wi-Fi disconnected. Reconnecting..."); } // Wait 15 seconds (ThingSpeak free-tier update interval constraint) delay(15000); }

Asset 2: Python Cloud Data Ingest Script (`query_telemetry.py`)

Line-by-Line Code Breakdown

# Practice Project 6: Python Cloud Database Query Script import requests import sys def main(): # Channel parameters channel_id = "YOUR_CHANNEL_ID" # Replace with your numeric ThingSpeak Channel ID # URL endpoint to read the last 100 feeds from the channel read_url = f"https://api.thingspeak.com/channels/{channel_id}/feeds.json?results=100" print(f"Fetching data history feeds from ThingSpeak Read API endpoint...") try: # Execute GET request response = requests.get(read_url, timeout=10.0) # Check HTTP status code response.raise_for_status() # Parse JSON response data = response.json() except requests.RequestException as e: print(f"Error: Failed to fetch data. Details: {e}") sys.exit(1) feeds = data.get('feeds', []) if not feeds: print("No data entries found in the specified channel. Verify ESP32 updates.") sys.exit(0) print(f"Loaded {len(feeds)} records from database. Processing history...") print("==================================================") temperatures = [] lights = [] for feed in feeds: temp_str = feed.get('field1') light_str = feed.get('field2') if temp_str is not None: try: temperatures.append(float(temp_str)) except ValueError: pass if light_str is not None: try: lights.append(int(light_str)) except ValueError: pass # Calculate peak values if temperatures: max_temp = max(temperatures) min_temp = min(temperatures) avg_temp = sum(temperatures) / len(temperatures) print(f"[-] Temperature metrics - Max: {max_temp:.2f} C | Min: {min_temp:.2f} C | Avg: {avg_temp:.2f} C") if lights: max_light = max(lights) min_light = min(lights) print(f"[-] Light level metrics - Max: {max_light} | Min: {min_light}") print("==================================================") print("Analysis processing complete.") if __name__ == "__main__": main()
5. Deliverables Summary

Created Artifacts

  • ESP32 http POST script file: http_client.ino.
  • Python analysis database script: query_telemetry.py.
  • JSON telemetry feed dump file showing raw database arrays.

Verification Proof

  • Screenshots of the live ThingSpeak private channel view, displaying the line graphs and widget gauge updates.
  • Screenshot of your VM console terminal running query_telemetry.py, displaying calculated temperature ranges and average values.
6. Closing Explanation: Why We Did This & What It Accomplishes

Architectural Intent & Operational Impact

Why We Did This

What This Accomplishes