This is the last practice
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
Israel Herrera 0a6a99f9ad Readme 10 months ago
bmp180-library Code 10 months ago
data Code 10 months ago
htu21d-library Code 10 months ago
ui Code 10 months ago
BMP180 Code 10 months ago
HTU21D Code 10 months ago
README.md Readme 10 months ago

README.md

Air Quality Monitor

Air Quality Monitor is a lightweight web interface that displays real-time data from two environmental sensors: HTU21D and BMP180. The system uses NGINX to serve an HTML page that reads live data from JSON files.

Project Description

This project was designed to visualize environmental parameters in a simple, fast, and efficient way using an embedded graphical interface. The data is obtained from the following sensors:

  • HTU21D: Temperature and relative humidity.
  • BMP180: Atmospheric pressure and temperature.

The data is stored in two JSON files, updated by the embedded system and displayed through an HTML/JavaScript-based frontend.


Project Structure

air-quality-monitor/ │ ├── BMP180.json # Pressure and temperature data from BMP180 ├── HTU21D.json # Temperature and humidity data from HTU21D ├── index.html # Main web interface ├── index.js # JavaScript logic to fetch and display JSON data ├── style.css # Custom CSS styles

The .json files are automatically updated by C programs that communicate with the sensors via I2C.


🚀 Installation & Deployment with NGINX

Requirements

  • Linux server with nginx installed.
  • Root access or permission to modify NGINX configuration.

Steps

  1. Install NGINX (if not already installed):
sudo apt update
sudo apt install nginx
  1. Copy the project files to NGINXs public directory (e.g., /var/www/html):

  1. Redirect the configuration file to our repository folder:
sudo vi /etc/nginx/sites-available/default
  1. Replace the line:
root /var/www/html;

with:

root /home/debian/path/to/your/repository;
  1. Apply chages with:
sudo systemctl restart nginx

User interface

This is a simple web page that displays real-time sensor data from two devices: • BMP180: Shows temperature and pressure. • HTU21D: Shows humidity and temperature.

Its styled with a separate CSS file (style.css) and fetches live data using JavaScript (index.js), which likely reads values from two JSON files (BMP180.json and HTU21D.json).

HTML

Complete code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Sensor Dashboard</title>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <div class="background"></div>
  <div class="container">
    <h1>Sensor Dashboard</h1>
    
    <div class="sensor-card">
      <img src="https://cdn-icons-png.flaticon.com/512/1126/1126741.png" alt="Temperature & Pressure Icon">
      <h2>BMP180</h2>
      <div class="data">
        <span id="temperature">Temperature: -- °C</span>
        <span id="pressure">Pressure: -- hPa</span>
      </div>
    </div>

    <div class="sensor-card">
      <img src="https://cdn-icons-png.flaticon.com/512/728/728093.png" alt="Humidity Icon">
      <h2>HTU21D</h2>
      <div class="data">
        <span id="humidity">Humidity: -- %</span>
        <span id="tempHTU">Temperature: -- °C</span>
      </div>
    </div>
  </div>

  <script src="index.js"></script>
</body>
</html>

Explanation

<!DOCTYPE html>
<html lang="en">

• Declares this document as HTML5. • lang="en" sets the document language to English, which is useful for accessibility and SEO.

HEAD
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Sensor Dashboard</title>
  <link rel="stylesheet" href="style.css" />
</head>

• charset="UTF-8" ensures proper text encoding. • viewport makes the layout responsive on mobile devices. • title is what appears in the browser tab. • link imports the external CSS file (style.css) for styling.

BODY
<body>
  <div class="background"></div>
  <div class="container">
    ...
  </div>
  <script src="index.js"></script>
</body>

• The background div might be used for a visual effect like a background image or color gradient (defined in your CSS). • container holds the main content (dashboard). • index.js is loaded at the end to ensure the DOM is ready before scripts run.

Dashboard Title
<h1>Sensor Dashboard</h1>

• This is the main heading of your web page.

Sensor Card: BMP180
<div class="sensor-card">
  <img src="https://cdn-icons-png.flaticon.com/512/1126/1126741.png" alt="Temperature & Pressure Icon">
  <h2>BMP180</h2>
  <div class="data">
    <span id="temperature">Temperature: -- °C</span>
    <span id="pressure">Pressure: -- hPa</span>
  </div>
</div>

• This block represents the BMP180 sensor. • The icon (from flaticon.com) visually represents pressure/temperature. • The id attributes (temperature, pressure) are hooks used by JavaScript to insert real values from BMP180.json.

Sensor Card: HTU21D
<div class="sensor-card">
  <img src="https://cdn-icons-png.flaticon.com/512/728/728093.png" alt="Humidity Icon">
  <h2>HTU21D</h2>
  <div class="data">
    <span id="humidity">Humidity: -- %</span>
    <span id="tempHTU">Temperature: -- °C</span>
  </div>
</div>

• This block represents the HTU21D sensor. • The image is a humidity icon. • The id attributes (humidity, tempHTU) are also updated by JavaScript using HTU21D.json.

JavaScript Integration
<script src="index.js"></script>

• This line loads your script, which is responsible for: • Fetching the JSON files. • Parsing their content. • Replacing the placeholder values (-- °C, -- hPa, etc.) with live sensor data.

Index.js

The script fetches data from two local JSON files: • BMP180.json — contains temperature and pressure. • HTU21D.json — contains temperature and humidity.

Then it updates the HTML every 3 seconds so the page always shows live sensor values.

Full code

function updateBMP180() {
  fetch('BMP180.json')
    .then(res => res.json())
    .then(data => {
      document.getElementById('temperature').textContent = `Temperature: ${data.temperature.toFixed(2)} °C`;
      document.getElementById('pressure').textContent = `Pressure: ${data.pressure.toFixed(2)} hPa`;
    })
    .catch(err => console.error("Error BMP180:", err));
}

function updateHTU21D() {
  fetch('HTU21D.json')
    .then(res => res.json())
    .then(data => {
      document.getElementById('humidity').textContent = `Humidity: ${data.humidity.toFixed(1)} %`;
      document.getElementById('tempHTU').textContent = `Temperature: ${data.temperature.toFixed(1)} °C`;
    })
    .catch(err => console.error("Error HTU21D:", err));
}

setInterval(() => {
  updateBMP180();
  updateHTU21D();
}, 3000);

// Carga inicial
updateBMP180();
updateHTU21D();

Code explanation

Function: updateBMP180

function updateBMP180() {
  fetch('BMP180.json')
    .then(res => res.json())
    .then(data => {
      document.getElementById('temperature').textContent = `Temperature: ${data.temperature.toFixed(2)} °C`;
      document.getElementById('pressure').textContent = `Pressure: ${data.pressure.toFixed(2)} hPa`;
    })
    .catch(err => console.error("Error BMP180:", err));
}
  • This defines a new function named updateBMP180. Youll call this function when you want to update the BMP180 sensor data on the page.
  • fetch('BMP180.json'): Loads the JSON file from the same directory.
  • .then(res =>json()): Parses the response as JSON
  • .then(data +> {}): Accesses the data inside the file.
  • document.getElementById(...) updates the corresponding elements in your HTML.

Function: updateHTU21D

function updateHTU21D() {
  fetch('HTU21D.json')
    .then(res => res.json())
    .then(data => {
      document.getElementById('humidity').textContent = `Humidity: ${data.humidity.toFixed(1)} %`;
      document.getElementById('tempHTU').textContent = `Temperature: ${data.temperature.toFixed(1)} °C`;
    })
    .catch(err => console.error("Error HTU21D:", err));
}

Works the same way as updateBMP180(), but:

  • Fetches from HTU21D.json.
  • Displays humidity and temperature.
  • Uses .toFixed(1) for 1 decimal place (common for humidity values).

Auto-update every 3 seconds

setInterval(() => {
  updateBMP180();
  updateHTU21D();
}, 3000);
  • Calls both update functions every 3,000 milliseconds (3 seconds).
  • Keeps the UI in sync with new sensor readings, assuming the .json files are being updated continuously.

Initial load

updateBMP180();
updateHTU21D();
  • Ensures the data is shown immediately on page load, before the 3-second interval kicks in.

CSS

Full code

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Segoe UI", sans-serif;
}

body, html {
  height: 100%;
  background-color: #0d1117;
  color: #ffffff;
  position: relative;
  overflow: hidden;
}

.background {
  background-image: url('https://wallpapers.com/images/hd/blue-circuit-board-traces-zn0xezd4t8axj9r6.webp');
  background-size: cover;
  background-position: center;
  opacity: 0.1;
  filter: blur(3px);
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
}

.container {
  max-width: 800px;
  margin: 40px auto;
  background-color: #161b22;
  padding: 30px;
  border-radius: 20px;
  box-shadow: 0 0 30px rgba(0, 255, 255, 0.2);
  animation: fadeIn 1s ease-in;
}

h1 {
  text-align: center;
  margin-bottom: 30px;
  font-size: 2.5rem;
  color: #58a6ff;
}

.sensor-card {
  background-color: #1f2937;
  padding: 20px;
  border-radius: 15px;
  margin-bottom: 20px;
  box-shadow: 0 0 20px rgba(100, 255, 255, 0.1);
  animation: slideIn 1s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.sensor-card img {
  width: 64px;
  height: 64px;
  margin-bottom: 10px;
}

.sensor-card h2 {
  margin-bottom: 10px;
  color: #90cdf4;
}

.data span {
  display: block;
  margin: 5px 0;
  font-size: 1.2rem;
  color: #ffffff;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(-20px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slideIn {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}

Explaining

Global Styling

  • *: Resets default browser spacing (margin, padding) and sets a consistent font and box model across the entire page.
  • body, html:
  • Sets full height layout.
  • Applies a dark background (#0d1117) with white text.
  • Hides overflow and enables positioning for internal layers.

Background Layer

  • .background:
  • Adds a faint, blurred circuit board image as the background.
  • Uses opacity: 0.1 and filter: blur(3px) to give it a soft tech feel.
  • Positioned absolutely behind everything (z-index: -1).

Main Container

  • .container:
  • A centered, card-like section with:
  • A dark background (#161b22)
  • Rounded corners and soft glowing shadow.
  • Padding and a fade-in animation on load.

Title

  • h1:
  • Large, centered header in light blue (#58a6ff).
  • Styled to stand out at the top of the dashboard.

Sensor Cards

  • .sensor-card:
  • Styled boxes for each sensor.
  • Darker background (#1f2937) with a soft shadow.
  • Rounded corners, padding, and a slide-in animation when they load.
  • Contents are centered vertically and horizontally.
  • .sensor-card img:
  • Sensor icons sized to 64×64 pixels with margin for spacing.
  • .sensor-card h2:
  • Sub-headers for each sensor card in a soft blue (#90cdf4).

Data Text

  • .data span:
  • Each line of sensor data (e.g., temperature, humidity).
  • Displayed as blocks with spacing and larger font for visibility.

Animations

  • @keyframes fadeIn:
  • Smooth slide-down + fade-in for the container.
  • @keyframes slideIn:
  • Subtle zoom-in effect for each sensor card.

Sensor library

HTU21D library

The library contains 3 files, HTU21D.c, htu21d.h and main.c

htu21d.h

#ifndef HTU21D_H
#define HTU21D_H

// HTU21D i2c address
#define HTU21D_ADDR 0x40

//commands for readings
#define HTU21D_TEMP 0xE3
#define HTU21D_HUM 0xE5
#define HTU21D_RESET 0xFE

//funtion declarations

//Temp:
int getTemp(int fd, double *temp);
//HUM
int getHum(int fd, double *hum);
//RESET
int getReset(int fd);
#endif

  • HTU21D_ADDR: The I2C address of the sensor (0x40).
  • HTU21D_TEMP: Command to read temperature (0xE3).
  • HTU21D_HUM: Command to read humidity (0xE5).
  • HTU21D_RESET: Command to reset the sensor (0xFE).
  • Declares three functions:
  1. getTemp() for reading temperature,
  2. getHum() for reading humidity,
  3. getReset() for resetting the sensor.