#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#include <RTClib.h>
/* ---------------- PINS ---------------- */
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define ULTRA_TRIG 5
#define ULTRA_ECHO 18
#define PIR_PIN 19
#define PIR2_Pin 32
#define BUZ_PIN 23
#define BTN_PIN 0
#define LED_PIN 2
#define SDA_PIN 21
#define SCL_PIN 22
#define LDR_PIN 34
#define MQ2_PIN 35
/* ---------------- WIFI ---------------- */
const char* ssid = "Wokwi-GUEST";
const char* password = "";
#define channel 6
WebServer server(80);
/* ---------------- OBJECTS ---------------- */
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
DHT dht(DHT_PIN, DHT_TYPE);
RTC_DS3231 rtc;
/* ---------------- VARIABLES ---------------- */
float temp = 0, hum = 0;
long distance = 0;
int motion = 0, ldr = 0, mq2 = 0;
int activityScore = 0;
bool rtcOk = false;
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Smart Nursing Home Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body class="bg-gray-900 text-white p-6">
<h1 class="text-xl font-bold mb-4">Smart Nursing Home — Monitoring</h1>
<!-- TOP VALUES -->
<div class="grid grid-cols-12 gap-4">
<div class="col-span-3 bg-gray-800 p-4 rounded">
<p>Temperature</p>
<p id="tempVal" class="text-3xl font-bold">--°C</p>
</div>
<div class="col-span-3 bg-gray-800 p-4 rounded">
<p>Humidity</p>
<p id="humVal" class="text-3xl font-bold text-cyan-400">--%</p>
</div>
<div class="col-span-3 bg-gray-800 p-4 rounded">
<p>Gas</p>
<p id="gasVal" class="text-2xl font-bold text-yellow-400">--</p>
</div>
<div class="col-span-3 bg-gray-800 p-4 rounded">
<p>Light</p>
<p id="lightVal" class="text-2xl font-bold text-yellow-300">-- lux</p>
</div>
</div>
<!-- SMALL COMPACT CHARTS -->
<div class="grid grid-cols-2 gap-4 mt-6">
<div class="bg-gray-800 p-3 rounded">
<canvas id="tempChart" height="100"></canvas>
</div>
<div class="bg-gray-800 p-3 rounded">
<canvas id="humChart" height="100"></canvas>
</div>
<div class="bg-gray-800 p-3 rounded">
<canvas id="gasChart" height="100"></canvas>
</div>
<div class="bg-gray-800 p-3 rounded">
<canvas id="lightChart" height="100"></canvas>
</div>
<div class="bg-gray-800 p-3 rounded col-span-2">
<canvas id="distChart" height="110"></canvas>
</div>
</div>
<script>
let tData=[], hData=[], gData=[], lData=[], dData=[];
let labels=[];
function makeChart(id,label,color,dataRef){
return new Chart(document.getElementById(id),{
type:"line",
data:{
labels:labels,
datasets:[{
label:label,
data:dataRef,
borderColor:color,
borderWidth:2,
pointRadius:0,
tension:0.3
}]
},
options:{
animation:false,
plugins:{legend:{display:false}},
scales:{y:{beginAtZero:true}}
}
});
}
let tempChart=makeChart("tempChart","Temp","red",tData);
let humChart =makeChart("humChart","Hum","cyan",hData);
let gasChart =makeChart("gasChart","Gas","yellow",gData);
let lightChart=makeChart("lightChart","Light","orange",lData);
let distChart =makeChart("distChart","Distance","lime",dData);
async function loadData(){
let r=await fetch("/data");
let d=await r.json();
document.getElementById("tempVal").innerText=d.temp+"°C";
document.getElementById("humVal").innerText=d.hum+"%";
document.getElementById("gasVal").innerText=d.gas;
document.getElementById("lightVal").innerText=d.light+" lux";
if(labels.length>25){
labels.shift();tData.shift();hData.shift();gData.shift();lData.shift();dData.shift();
}
labels.push("");
tData.push(d.temp);
hData.push(d.hum);
gData.push(d.gas);
lData.push(d.light);
dData.push(d.distance);
tempChart.update();
humChart.update();
gasChart.update();
lightChart.update();
distChart.update();
}
setInterval(loadData,2000);
</script>
</body>
</html>
)=====";
/* ------------- TASK DECLARATIONS -------------*/
void taskEnvironment(void *pvParameters);
void taskActivity(void *pvParameters);
/* ---------------- SETUP ---------------- */
void setup() {
Serial.begin(115200);
pinMode(ULTRA_TRIG, OUTPUT);
pinMode(ULTRA_ECHO, INPUT);
pinMode(PIR_PIN, INPUT);
pinMode(BUZ_PIN, OUTPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
Wire.begin(SDA_PIN, SCL_PIN);
dht.begin();
if (rtc.begin()) rtcOk = true;
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay();
WiFi.begin(ssid, password, channel);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("Connected");
Serial.println(WiFi.localIP());
/* -------- WEB ROUTES -------- */
server.on("/", []() {
server.send(200, "text/html", MAIN_page);
});
server.on("/data", []() {
String json = "{";
json += "\"temp\":" + String(temp) + ",";
json += "\"hum\":" + String(hum) + ",";
json += "\"distance\":" + String(distance) + ",";
json += "\"motion\":" + String(motion) + ",";
json += "\"gas\":" + String(mq2) + ",";
json += "\"light\":" + String(ldr);
json += "}";
server.send(200, "application/json", json);
});
server.begin();
xTaskCreate(taskEnvironment,"env",2048,NULL,2,NULL);
xTaskCreate(taskActivity,"act",2048,NULL,2,NULL);
}
/* ---------------- LOOP ---------------- */
void loop() {
server.handleClient();
}
/* ---------------- TASKS ---------------- */
void taskEnvironment(void*) {
for(;;){
temp=dht.readTemperature();
hum=dht.readHumidity();
ldr=analogRead(LDR_PIN);
mq2=analogRead(MQ2_PIN);
vTaskDelay(3000/portTICK_PERIOD_MS);
}
}
void taskActivity(void*) {
for(;;){
digitalWrite(ULTRA_TRIG, LOW); delayMicroseconds(2);
digitalWrite(ULTRA_TRIG, HIGH); delayMicroseconds(10);
digitalWrite(ULTRA_TRIG, LOW);
long d=pulseIn(ULTRA_ECHO,HIGH,25000);
distance=d*0.034/2;
motion=digitalRead(PIR_PIN);
if(motion) activityScore++;
vTaskDelay(500/portTICK_PERIOD_MS);
}
}