Skip to content
Snippets Groups Projects
Commit 6d7af787 authored by Vojtěch Novotný's avatar Vojtěch Novotný
Browse files

Merge branch 'develop' into 'main'

Develop

See merge request !3
parents 30747b4c d7fc1936
No related branches found
No related tags found
1 merge request!3Develop
#include <WiFi.h>
#include <HTTPClient.h>
#include <DHT.h>
// WiFi credentials
const char *ssid = "WIFI_NAME";
const char *password = "PWIFI_PW";
// Server url
const char *serverUrl = "http://1a68d31fc96915376990672871a32080.serveo.net/docs/thproject/index.php?p=";
// DHT sensor setup
#define DHTPIN 18 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
// Room identification - this varies for each ESP32, replace "room1", "room2", ...
const String roomId = "roomX";
// Time between measurements (in milliseconds)
const unsigned long interval = 60000; // 1 minute
unsigned long previousMillis = 0;
void setup()
{
Serial.begin(115200);
// Initialize DHT sensor
dht.begin();
// Connect to WiFi
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi...");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi Connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop()
{
unsigned long currentMillis = millis();
// Check if it's time to send data
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
// Read temperature and humidity
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// Check if readings are valid
if (isnan(humidity) || isnan(temperature))
{
Serial.println("Failed to read from DHT sensor!");
return;
}
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print(" °C, Humidity: ");
Serial.print(humidity);
Serial.println(" %");
// Send data to server
sendDataToServer(temperature, humidity, roomId);
}
}
void sendDataToServer(float temperature, float humidity, String room)
{
// Check WiFi connection status
if (WiFi.status() == WL_CONNECTED)
{
HTTPClient http;
// Construct the URL with parameters
String url = String(serverUrl) + "data&room=" + room + "&temp=" + temperature + "&humidity=" + humidity;
// Begin HTTP connection
http.begin(url);
// Send HTTP GET request
int httpResponseCode = http.GET();
if (httpResponseCode > 0)
{
String response = http.getString();
Serial.println("HTTP Response code: " + String(httpResponseCode));
Serial.println("Response: " + response);
}
else
{
Serial.print("HTTP Error: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
}
else
{
Serial.println("WiFi Disconnected");
// Attempt to reconnect
WiFi.reconnect();
}
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Monitoring Temperature & Humidity</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
.sensor-card { margin-bottom: 20px; }
.reading { font-size: 2rem; font-weight: bold; }
.timestamp { font-size: 0.8rem; color: #666; }
.chart-container { height: 150px; margin-top: 10px; }
.phone-view .reading { font-size: 4rem; }
.phone-view .chart-container, .phone-view .timestamp { display: none; }
.phone-view .sensor-card { display: inline-block; width: 48%; margin-right: 2%; }
.phone-view .sensor-card:nth-child(2n) { margin-right: 0; }
.editable-title { cursor: pointer; }
.editable-title input { display: none; width: 100%; }
</style>
</head>
<body>
<div class="container mt-4">
<h1 class="mb-4 text-center">Monitoring Temperature & Humidity</h1>
<button id="toggle-phone-view" class="btn btn-primary mb-4">Toggle Phone View</button>
<div class="row" id="sensor-data"></div>
</div>
<script src="script.js"></script>
</body>
</html>
\ No newline at end of file
<?php
// File to store sensor data as JSON
$dataFile = 'sensor_data.json';
// Check if this is a data submission
if (isset($_GET['p']) && $_GET['p'] == 'data') {
if (isset($_GET['room']) && isset($_GET['temp']) && isset($_GET['humidity'])) {
$room = $_GET['room'];
$temperature = floatval($_GET['temp']);
$humidity = floatval($_GET['humidity']);
$timestamp = time();
// Read existing data
$data = [];
if (file_exists($dataFile)) {
$fileContent = file_get_contents($dataFile);
if (!empty($fileContent)) {
$data = json_decode($fileContent, true);
}
}
// Add or update room data
if (!isset($data[$room])) {
$data[$room] = [
'temperatures' => [],
'humidities' => [],
'timestamps' => []
];
}
// Append new readings (limit to last 48 readings(one per half hour))
$data[$room]['temperatures'][] = $temperature;
$data[$room]['humidities'][] = $humidity;
$data[$room]['timestamps'][] = $timestamp;
if (count($data[$room]['temperatures']) > 48) {
array_shift($data[$room]['temperatures']);
array_shift($data[$room]['humidities']);
array_shift($data[$room]['timestamps']);
}
file_put_contents($dataFile, json_encode($data));
echo "Data received successfully";
} else {
echo "Error: Missing parameters";
}
exit;
}
// If we're getting data
if (isset($_GET['p']) && $_GET['p'] == 'get') {
header('Content-Type: application/json');
echo file_exists($dataFile) ? file_get_contents($dataFile) : '{}';
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Monitoring Temperature & Humidity</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
.sensor-card { margin-bottom: 20px; }
.reading { font-size: 2rem; font-weight: bold; }
.timestamp { font-size: 0.8rem; color: #666; }
.chart-container { height: 150px; margin-top: 10px; }
</style>
</head>
<body>
<div class="container mt-4">
<h1 class="mb-4">Monitoring Temperature & Humidity</h1>
<div class="row" id="sensor-data"></div>
</div>
<script>
function formatTimestamp(timestamp) {
return new Date(timestamp * 1000).toLocaleString();
}
function loadSensorData() {
fetch('index.php?p=get')
.then(response => response.json())
.then(data => {
const sensorContainer = document.getElementById('sensor-data');
sensorContainer.innerHTML = '';
if (Object.keys(data).length === 0) {
sensorContainer.innerHTML = '<div class="col-12"><div class="alert alert-warning">No sensor data available yet.</div></div>';
return;
}
let html = '';
for (const [room, readings] of Object.entries(data)) {
const roomName = room.charAt(0).toUpperCase() + room.slice(1);
const ageInMinutes = Math.floor((Date.now() / 1000 - readings.timestamps[readings.timestamps.length - 1]) / 60);
html += `
<div class="col-md-6">
<div class="card sensor-card">
<div class="card-header bg-primary text-white">${roomName}</div>
<div class="card-body">
<div class="reading text-center">${readings.temperatures.at(-1).toFixed(1)}°C</div>
<div class="reading text-center">${readings.humidities.at(-1).toFixed(1)}%</div>
<div class="timestamp text-center">Last updated: ${formatTimestamp(readings.timestamps.at(-1))}
${ageInMinutes > 5 ? `<div class="text-danger">(${ageInMinutes} minutes ago)</div>` : ''}
</div>
<div class="chart-container"><canvas id="temp-chart-${room}"></canvas></div>
<div class="chart-container"><canvas id="hum-chart-${room}"></canvas></div>
</div>
</div>
</div>`;
}
sensorContainer.innerHTML = html;
for (const [room, readings] of Object.entries(data)) {
renderChart(`temp-chart-${room}`, readings.temperatures, readings.timestamps, 'Temperature (°C)', 'rgba(255, 99, 132, 1)');
renderChart(`hum-chart-${room}`, readings.humidities, readings.timestamps, 'Humidity (%)', 'rgba(54, 162, 235, 1)');
}
})
.catch(error => {
console.error('Error loading sensor data:', error);
document.getElementById('sensor-data').innerHTML = '<div class="col-12"><div class="alert alert-danger">Error loading sensor data. Please try again later.</div></div>';
});
}
function renderChart(canvasId, dataPoints, timestamps, label, color) {
new Chart(document.getElementById(canvasId).getContext('2d'), {
type: 'line',
data: {
labels: timestamps.map(t => formatTimestamp(t)),
datasets: [{
label: label,
data: dataPoints,
borderColor: color,
backgroundColor: color.replace('1)', '0.2)'),
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: { x: { display: false }, y: { beginAtZero: false } },
plugins: { legend: { display: false } }
}
});
}
loadSensorData();
setInterval(loadSensorData, 30000);
</script>
</body>
</html>
\ No newline at end of file
let roomNames = {};
function formatTimestamp(timestamp) {
return new Date(timestamp * 1000).toLocaleString();
}
function loadSensorData() {
fetch('index.php?p=get')
.then(response => response.json())
.then(data => {
const sensorContainer = document.getElementById('sensor-data');
sensorContainer.innerHTML = '';
if (Object.keys(data.sensorData).length === 0) {
sensorContainer.innerHTML = '<div class="col-12"><div class="alert alert-warning">No sensor data available yet.</div></div>';
return;
}
roomNames = data.roomNames;
let html = '';
for (const [room, readings] of Object.entries(data.sensorData)) {
const roomName = roomNames[room] || (room.charAt(0).toUpperCase() + room.slice(1));
const ageInMinutes = Math.floor((Date.now() / 1000 - readings.timestamps[readings.timestamps.length - 1]) / 60);
html += `
<div class="col-md-6 sensor-card">
<div class="card">
<div class="card-header bg-primary text-white text-center editable-title" onclick="editTitle(this)">
<span>${roomName}</span>
<input type="text" value="${roomName}" onblur="saveTitle(this, '${room}')" onkeypress="handleKeyPress(event, this, '${room}')">
</div>
<div class="card-body">
<div class="reading text-center">${readings.temperatures.at(-1).toFixed(1)}°C</div>
<div class="reading text-center">${readings.humidities.at(-1).toFixed(1)}%</div>
<div class="timestamp text-center">Last updated: ${formatTimestamp(readings.timestamps.at(-1))}
${ageInMinutes > 5 ? `<div class="text-danger">(${ageInMinutes} minutes ago)</div>` : ''}
</div>
<div class="chart-container"><canvas id="temp-chart-${room}"></canvas></div>
<div class="chart-container"><canvas id="hum-chart-${room}"></canvas></div>
</div>
</div>
</div>`;
}
sensorContainer.innerHTML = html;
for (const [room, readings] of Object.entries(data.sensorData)) {
renderChart(`temp-chart-${room}`, readings.temperatures, readings.timestamps, 'Temperature (°C)', 'rgba(255, 99, 132, 1)');
renderChart(`hum-chart-${room}`, readings.humidities, readings.timestamps, 'Humidity (%)', 'rgba(54, 162, 235, 1)');
}
})
.catch(error => {
console.error('Error loading sensor data:', error);
document.getElementById('sensor-data').innerHTML = '<div class="col-12"><div class="alert alert-danger">Error loading sensor data. Please try again later.</div></div>';
});
}
function renderChart(canvasId, dataPoints, timestamps, label, color) {
new Chart(document.getElementById(canvasId).getContext('2d'), {
type: 'line',
data: {
labels: timestamps.map(t => formatTimestamp(t)),
datasets: [{
label: label,
data: dataPoints,
borderColor: color,
backgroundColor: color.replace('1)', '0.2)'),
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: { x: { display: false }, y: { beginAtZero: false } },
plugins: { legend: { display: false } }
}
});
}
function editTitle(element) {
const span = element.querySelector('span');
const input = element.querySelector('input');
span.style.display = 'none';
input.style.display = 'block';
input.focus();
}
function saveTitle(input, room) {
const span = input.previousElementSibling;
span.textContent = input.value;
input.style.display = 'none';
span.style.display = 'block';
roomNames[room] = input.value;
saveRoomNames();
}
function handleKeyPress(event, input, room) {
if (event.key === 'Enter') {
saveTitle(input, room);
}
}
function saveRoomNames() {
fetch('index.php?p=saveNames', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(roomNames)
})
.then(response => response.text())
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error saving room names:', error);
});
}
document.getElementById('toggle-phone-view').addEventListener('click', () => {
document.body.classList.toggle('phone-view');
});
loadSensorData();
setInterval(loadSensorData, 30000);
\ No newline at end of file
fsd
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment