diff --git a/README.md b/README.md new file mode 100644 index 0000000..9737800 --- /dev/null +++ b/README.md @@ -0,0 +1,459 @@ +# 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): +```bash +sudo apt update +sudo apt install nginx +``` +2. Copy the project files to NGINX’s public directory (e.g., /var/www/html): +``` bash + +``` +3. Redirect the configuration file to our repository folder: +```bash +sudo vi /etc/nginx/sites-available/default +``` +4. Replace the line: +```bash +root /var/www/html; +``` +with: +```bash +root /home/debian/path/to/your/repository; +``` +5. Apply chages with: +```bash +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. + +It’s 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 +```html + + + + + + Sensor Dashboard + + + +
+
+

Sensor Dashboard

+ +
+ Temperature & Pressure Icon +

BMP180

+
+ Temperature: -- °C + Pressure: -- hPa +
+
+ +
+ Humidity Icon +

HTU21D

+
+ Humidity: -- % + Temperature: -- °C +
+
+
+ + + + +``` +#### Explanation +```html + + +``` +• Declares this document as HTML5. +• lang="en" sets the document language to English, which is useful for accessibility and SEO. +##### HEAD +```html + + + + Sensor Dashboard + + +``` +• 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 +```html + +
+
+ ... +
+ + +``` +• 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 +```html +

Sensor Dashboard

+``` +• This is the main heading of your web page. +##### Sensor Card: BMP180 +```hmtl +
+ Temperature & Pressure Icon +

BMP180

+
+ Temperature: -- °C + Pressure: -- hPa +
+
+``` +• 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 +```html +
+ Humidity Icon +

HTU21D

+
+ Humidity: -- % + Temperature: -- °C +
+
+``` +• 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 +```hmtl + +``` +• 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 +```js +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 +```js +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. You’ll 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 +```js +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 +```js +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 +```js +updateBMP180(); +updateHTU21D(); +``` +- Ensures the data is shown immediately on page load, before the 3-second interval kicks in. +### CSS +#### Full code +```css +* { + 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 +```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. + +