#include <WiFi.h>
#include <WebServer.h>
#include "RTClib.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ======================================================
// Smart Process Monitor (Розумний монітор процесів)
// IoT-пристрій з AI-аналітикою для ESP32
// ======================================================
// ------------------- WiFi -------------------
const char* SSID = "Wokwi-GUEST";
const char* password = "";
// ------------------- OpenAI API -------------------
// ⚠️ Вкажи свій власний ключ OpenAI (Azure OpenAI)
const char* openaiApiKey = "b453666eb3d04c1fa7c608375d88f7fc";
// ------------------- RTC, Датчики -------------------
// RTC — годинник реального часу
RTC_DS1307 rtc;
// Потенціометр використовується як модель інтенсивності процесу (0–100%)
const int POT_PIN = 35;
// Вебсервер для локальної панелі моніторингу
WebServer server(80);
// ------------------- OLED -------------------
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
TwoWire I2COLED = TwoWire(1);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &I2COLED);
// ------------------- Дані -------------------
String dataValue = "Loading...";
String recommendation = "No insights yet"; // Відповідь від GPT
String history[10]; // Масив останніх вимірів
int historyIndex = 0;
// ======================================================
// HTML ІНТЕРФЕЙС
// ======================================================
void sendHtml() {
String html = R"rawliteral(
<html>
<head>
<meta charset='utf-8'>
<title>Smart Process Monitor</title>
<style>
body { font-family: Arial; background:#eef1f4; margin:20px; }
h2 { color:#333; }
.card { background:#fff; padding:15px; border-radius:10px; box-shadow:0 0 10px rgba(0,0,0,0.15); }
button { padding:10px 15px; margin-top:10px; border:none; border-radius:5px; background:#1976D2; color:white; cursor:pointer; }
button:hover { background:#0D47A1; }
pre { font-size:14px; background:#eee; padding:10px; border-radius:5px; }
</style>
<script>
// Автоматичне оновлення сторінки кожні 5 секунд
async function updateData() {
let res = await fetch('/');
let text = await res.text();
document.body.innerHTML = text;
}
// Запит до AI для аналізу даних
async function getRec() {
let res = await fetch('/update?value=rec');
let text = await res.text();
document.body.innerHTML = text;
}
setInterval(updateData, 5000);
</script>
</head>
<body>
<div class='card'>
<h2>Smart Process Monitor</h2>
<pre>)rawliteral";
html += dataValue;
html += R"rawliteral(</pre>
<p><b>AI Insights:</b> )rawliteral" + recommendation + R"rawliteral(</p>
<button onclick="getRec()">Аналізувати дані</button>
</div>
</body>
</html>
)rawliteral";
server.send(200, "text/html", html);
}
void handleRoot() { sendHtml(); }
// ======================================================
// GPT — АНАЛІЗ ДАНИХ
// ======================================================
void request_gpt(String prompt) {
DynamicJsonDocument jsonDocument(4096);
jsonDocument["model"] = "gpt-3.5-turbo";
JsonArray messages = jsonDocument.createNestedArray("messages");
// Системне повідомлення для налаштування поведінки моделі
JsonObject sys = messages.createNestedObject();
sys["role"] = "system";
sys["content"] =
"You are an AI system that analyzes technical process data based on sensor readings. "
"Your goal is to detect trends, fluctuations, and stability levels. "
"Provide concise insights or predictions about the ongoing process.";
// Додаємо історію вимірів
String historyPrompt = "Recent data history:\n";
for (int i = 0; i < 10; i++) {
if (history[i] != "") historyPrompt += history[i] + "\n";
}
// Поточні дані
JsonObject usr = messages.createNestedObject();
usr["role"] = "user";
usr["content"] = historyPrompt + "\nCurrent data:\n" + prompt;
HTTPClient http;
String apiUrl = "https://artificialintelligence.openai.azure.com/openai/deployments/test/chat/completions?api-version=2023-05-15";
http.begin(apiUrl);
http.addHeader("Content-Type", "application/json");
http.addHeader("api-key", openaiApiKey);
String body;
serializeJson(jsonDocument, body);
// Відправлення запиту до OpenAI API
int httpCode = http.POST(body);
if (httpCode == 200) {
String response = http.getString();
DynamicJsonDocument resDoc(8192);
deserializeJson(resDoc, response);
recommendation = resDoc["choices"][0]["message"]["content"].as<String>();
Serial.println("AI Insights: " + recommendation);
} else {
recommendation = "Помилка: " + String(httpCode);
Serial.println(recommendation);
}
http.end();
}
void handleUpdate() {
if (server.hasArg("value")) {
if (server.arg("value") == "rec") {
request_gpt(dataValue);
}
}
sendHtml();
}
// ======================================================
// SETUP
// ======================================================
void setup() {
Serial.begin(115200);
pinMode(POT_PIN, INPUT);
// Ініціалізація RTC
Wire.begin(21, 22);
if (!rtc.begin()) Serial.println("⚠️ RTC не знайдено");
// Ініціалізація OLED-дисплея
I2COLED.begin(14, 12);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) Serial.println("⚠️ Помилка ініціалізації OLED");
display.clearDisplay();
// Підключення до Wi-Fi
WiFi.begin(SSID, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\n✅ Wi-Fi підключено");
Serial.println("🌐 IP адреса: " + WiFi.localIP().toString());
// Запуск локального вебсервера
server.on("/", handleRoot);
server.on("/update", handleUpdate);
server.begin();
}
// ======================================================
// LOOP
// ======================================================
void loop() {
server.handleClient();
// Отримуємо поточний час з RTC
DateTime now = rtc.now();
String Time = String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second());
// Зчитуємо дані з потенціометра та переводимо у відсотки
int potValue = analogRead(POT_PIN);
int intensity = map(potValue, 0, 4095, 0, 100);
String Intensity = String(intensity) + "%";
// Формуємо текстові дані для відображення
dataValue = "Time: " + Time + "\n" +
"Process Intensity: " + Intensity + "\n";
// Зберігаємо історію вимірів (10 останніх значень)
history[historyIndex] = dataValue;
historyIndex = (historyIndex + 1) % 10;
// Виводимо інформацію на OLED-дисплей
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Process Monitor");
display.println("Time: " + Time);
display.println("Intensity: " + Intensity);
display.display();
delay(1000);
}