/* ESP32 HTTP IoT Server Example for Wokwi.com
https://wokwi.com/projects/320964045035274834
Application: 05
Class: Real Time Systems EEE4775- Sp 2026
Author: [Abdel]
Email: [[email protected]]
Company: [University of Central Florida]
//Note: I am saving a copy of this project of URI to my project since i connected this project to WIFI
and since I do not have a specific library (or know how)that can get the project at least to start for some demo.
To test, you need the Wokwi IoT Gateway, as explained here:
https://docs.wokwi.com/guides/esp32-wifi#the-private-gateway
Then start the simulation, and open http://localhost:9080
in another browser tab.
Note that the IoT Gateway requires a Wokwi Club subscription.
To purchase a Wokwi Club subscription, go to https://wokwi.com/club
*/
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <uri/UriBraces.h>
#include "freertos/task.h"
#include "freertos/semphr.h"
#include <driver/adc.h>
#include "freertos/FreeRTOS.h"
// Defining the WiFi channel speeds up the connection:
#define WIFI_CHANNEL 6
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
WebServer server(80);
bool systemInAlertMode = false; // Initial safe state AI generated
bool led1State = false;
bool led2State = false;
const int LED1 = 26;
const int LED2 = 27;
const int GREEN_LED = 5; // Green LED for heartbeat/mode
const int RED_LED = 4; // Red LED for alerts
const int POTENTIOMETER = 34; // Potentiometer on ADC1_CH6
const int BUTTON_PIN = 12; // Pushbutton
//Set up binary Semaphores:
SemaphoreHandle_t sensorSemaphore; // Counting semaphore
SemaphoreHandle_t buttonSemaphore; // Binary semaphore for button push
SemaphoreHandle_t webToggleSemaphore; // Binary semaphore synchronize tasks to manage state changes from a web interface.
//Tasks handeles:
TaskHandle_t sensorMonitorTaskHandle = NULL;
TaskHandle_t buttonWatchTaskHandle = NULL;
TaskHandle_t eventResponseTaskHandle = NULL;
TaskHandle_t SystemHeartbeatTaskHandle = NULL;
// Function declaration:
void sendHtml();
void sensorMonitorTask(void *pvParameters);
void butonWatchTask(void *pvParameters);
void eventResponseTask(void *pvParameters);
void SystemHeartbeatTask(void *pvParameters);
//Web server handel AI generated to send HTML content when visiting IP address of the device
void sendHtml() {
sendHtml();
}
void sendHtml() {
String response = R"(
<!DOCTYPE html><html>
<head>
<title>ESP32 Web Server Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html { font-family: sans-serif; text-align: center; }
body { display: inline-flex; flex-direction: column; }
h1 { margin-bottom: 1.2em; }
h2 { margin: 0; }
div { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; grid-auto-flow: column; grid-gap: 1em; }
.btn { background-color: #5B5; border: none; color: #fff; padding: 0.5em 1em;
font-size: 2em; text-decoration: none }
.btn.OFF { background-color: #333; }
</style>
</head>
<body>
<h1>ESP32 Web Server</h1>
<div>
<h2>LED 1</h2>
<a href="/toggle/1" class="btn LED1_TEXT">LED1_TEXT</a>
<h2>LED 2</h2>
<a href="/toggle/2" class="btn LED2_TEXT">LED2_TEXT</a>
</div>
</body>
</html>
)";
response.replace("LED1_TEXT", led1State ? "ON" : "OFF");
response.replace("LED2_TEXT", led2State ? "ON" : "OFF");
server.send(200, "text/html", response);
response.replace("ALERT_STATUS_TEXT", systemInAlertMode ? "ACTIVE" : "NORMAL");
}
void setup(void) {
Serial.begin(115200);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP); // Internal pull-up
//ADC Configuration
adc1_config_width(ADC_WIDTH_BIT_12); // 0-4095 range AI generated
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); // GPIO34 @t ADC1_CH6
//WIFI SET UP CONFIGURATION
WiFi.begin(WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL);
Serial.print("Connecting to WiFi ");
Serial.print(WIFI_SSID);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on("/", sendHtml);
server.on(UriBraces("/toggle/{}"), []() {
String led = server.pathArg(0);
Serial.print("Toggle LED #");
Serial.println(led);
switch (led.toInt()) {
case 1:
led1State = !led1State;
digitalWrite(LED1, led1State);
break;
case 2:
led2State = !led2State;
digitalWrite(LED2, led2State);
break;
}
sendHtml();
});
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
server.handleClient();
delay(2);
}
// Create Semaphores
sensorSemaphore = xSemaphoreCreateCounting(10, 0); // Max 10 alerts queued
buttonSemaphore = xSemaphoreCreateBinary();
webToggleSemaphore = xSemaphoreCreateBinary();
SemaphoreHandle_t sensorSemaphore; // Counting semaphore
SemaphoreHandle_t buttonSemaphore; // Binary semaphore for button push
SemaphoreHandle_t webToggleSemaphore; // Binary semaphore synchronize t
// Create Tasks
xTaskCreatePinnedToCore(sensorMonitorTask,"sensorMonitor",2048, NULL,2,&sensorMonitorTaskHandle,0 ); //Priority 2 and core 0
xTaskCreatePinnedToCore(buttonWatchTask,"buttonWatch",2048,NULL,4,&buttonWatchTaskHandle,0);//priority 4 core 0
xTaskCreatePinnedToCore(eventResponseTask,"eventResponse",4096, NULL,3, &eventResponseTaskHandle,1); // Priority 3 and Core 1
xTaskCreatePinnedToCore(heartbeatTask,"Heartbeat",1024,NULL,1,&heartbeatTaskHandle,0); //Priority 1 and core 0
void loop() { //AI generated
// The loop() function should primarily handle web server client requests
// as the other logic is now managed by FreeRTOS tasks.
server.handleClient();
vTaskDelay(pdMS_TO_TICKS(2)); // Small delay to yield to other tasks
}
// .....................Assign Tasks:Most of these line codes are generated by AI............................
// SensorMonitor Task:
void sensorMonitorTask(void *pvParameters) {
const int SENSOR_THRESHOLD = 2000;
bool aboveThresholdLastRead = false;
unsigned long lastPrintTime = 0; // track time
const unsigned long PRINT_INTERVAL_MS = 500; //every 500ms print
for (;;) {
int sensorValue = adc1_get_raw(ADC1_CHANNEL_6);
if (millis() - lastPrintTime >= PRINT_INTERVAL_MS) {
Serial.print("For security, Please Check the Value: ");
Serial.println(sensorValue);
lastPrintTime = millis(); // Update the last print time
}
if (sensorValue > SENSOR_THRESHOLD && !aboveThresholdLastRead) {
Serial.println("SENSOR ALERT: HARDWARE SECURITY CHECK");
xSemaphoreGive(sensorAlertSemaphore); // Signal an alert
aboveThresholdLastRead = true;
} else if (sensorValue <= SENSOR_THRESHOLD && aboveThresholdLastRead) {
aboveThresholdLastRead = false;
}
vTaskDelay(pdMS_TO_TICKS(17)); // Read every 17 ms
}
}
//ButtonWatchTask:
void buttonWatchTask(void *pvParameters) {
bool lastButtonState = HIGH;
long lastDebounceTime = 0;
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (currentButtonState == LOW && lastButtonState == HIGH) { // Button pressed
Serial.println("BUTTON PRESS DETECTED!");
xSemaphoreGive(buttonPressSemaphore); // Signal a button event
}
}
lastButtonState = currentButtonState;
vTaskDelay(pdMS_TO_TICKS(10)); // Check button every 10 ms
}
}
void eventResponseTask(void *pvParameters) {
while(true){
Serial.println("EventResponse: Handling Sensor Alert!");
systemInAlertMode = true; // Set global alert state
digitalWrite(RED_LED, HIGH); // Turn on red LED
vTaskDelayUntil(pdMS_TO_TICKS(200)); // Brief flash
digitalWrite(RED_LED, LOW);
vTaskDelayUntil(pdMS_TO_TICKS(200));
digitalWrite(RED_LED, HIGH); // Second brief flash
vTaskDelayUntil(pdMS_TO_TICKS(200));
digitalWrite(RED_LED, LOW);
Serial.println("EventResponse: Red LED blinked.");
// rely on the browser refreshing or polling.
// server.send(200, "text/html", sendHtml()); // Not recommended to call directly from task
}
// Example: toggle green LED based on alert mode
digitalWrite(GREEN_LED, systemInAlertMode ? HIGH : LOW);
// Example: toggle LED1 via button (repurposing original LED logic)
led1State = !led1State;
digitalWrite(LED1, led1State);
}
Serial.println("EventResponse: Handling Web Toggle!");
digitalWrite(LED1, led1State);
digitalWrite(LED2, led2State);
Serial.println("EventResponse: Web-controlled LEDs updated.");
}
// If no events, yield to allow other tasks to run.
vTaskDelay(pdMS_TO_TICKS(10)); // Small delay to prevent busy-waiting
}
}
void heartbeatTask(void *pvParameters) {
for (;;) {
digitalWrite(GREEN_LED, HIGH);
vTaskDelayUntil(pdMS_TO_TICKS(250));
digitalWrite(GREEN_LED, LOW);
vTaskDelayUntil(pdMS_TO_TICKS(750)); // Blink green LED every second (250ms on, 750ms off)
}
}