157 lines
4.6 KiB
C++
157 lines
4.6 KiB
C++
#include <SoftwareSerial.h>
|
||
|
||
SoftwareSerial esp8266(4, 5); // RX, TX
|
||
|
||
// صفحه پیشفرض HTML
|
||
const char* HTML_PAGE = "<!DOCTYPE html><html><body><h2>Hello from ESP8266</h2></body></html>";
|
||
|
||
void setup() {
|
||
Serial.begin(9600);
|
||
esp8266.begin(9600);
|
||
|
||
delay(2000); // آمادهسازی ESP
|
||
|
||
// تنظیمات اولیه ESP8266
|
||
sendCommand("AT", "OK", 2000);
|
||
sendCommand("ATE0", "OK", 2000);
|
||
sendCommand("AT+CWMODE=2", "OK", 2000);
|
||
sendCommand("AT+CWSAP=\"ESP8266_AP\",\"12345678\",1,0", "OK", 5000);
|
||
sendCommand("AT+CIPMUX=1", "OK", 3000);
|
||
sendCommand("AT+CIPSERVER=1,80", "OK", 3000);
|
||
|
||
Serial.println(F("ESP8266 Ready. Connect to SSID: ESP8266_AP, Pass: 12345678"));
|
||
Serial.println(F("Then open http://192.168.4.1/ in your browser"));
|
||
}
|
||
|
||
void loop() {
|
||
if (esp8266.available()) {
|
||
String line = esp8266.readStringUntil('\n');
|
||
line.trim();
|
||
if (line.length() == 0) return;
|
||
|
||
Serial.println("[ESP8266] " + line);
|
||
|
||
if (line.startsWith("+IPD,")) {
|
||
int len = 0;
|
||
int linkId = parseIPDLine(line, len);
|
||
if (linkId < 0) {
|
||
Serial.println("Failed to parse IPD line.");
|
||
return;
|
||
}
|
||
|
||
drainPayload(len);
|
||
|
||
// فراخوانی تابع پردازش و ارسال پاسخ
|
||
processAndSend(linkId, line);
|
||
}
|
||
}
|
||
}
|
||
|
||
// =================== توابع کمکی ===================
|
||
|
||
// تابع پردازش داده و ارسال پاسخ به کلاینت
|
||
void processAndSend(int linkId, const String &requestLine) {
|
||
String html;
|
||
|
||
// بررسی پارامتر صفحه در URL
|
||
if (requestLine.indexOf("GET /?page=") != -1) {
|
||
int start = requestLine.indexOf("GET /?page=") + 10;
|
||
int end = requestLine.indexOf(" ", start);
|
||
int pageNum = requestLine.substring(start, end).toInt();
|
||
|
||
switch (pageNum) {
|
||
case 1:
|
||
html = "<!DOCTYPE html><html><body><h2>صفحه ۱</h2></body></html>";
|
||
break;
|
||
case 2:
|
||
html = "<!DOCTYPE html><html><body><h2>صفحه ۲</h2></body></html>";
|
||
break;
|
||
case 3:
|
||
html = "<!DOCTYPE html><html><body><h2>صفحه ۳</h2></body></html>";
|
||
break;
|
||
default:
|
||
html = "<!DOCTYPE html><html><body><h2>صفحه پیشفرض</h2></body></html>";
|
||
break;
|
||
}
|
||
} else {
|
||
html = HTML_PAGE; // صفحه پیشفرض
|
||
}
|
||
|
||
// ساخت پاسخ HTTP
|
||
String response = "HTTP/1.1 200 OK\r\n";
|
||
response += "Content-Type: text/html\r\n";
|
||
response += "Content-Length: " + String(html.length()) + "\r\n";
|
||
response += "Connection: close\r\n\r\n";
|
||
response += html;
|
||
|
||
// ارسال پاسخ
|
||
String cmd = "AT+CIPSEND=" + String(linkId) + "," + String(response.length());
|
||
if (sendCommand(cmd, ">", 5000)) {
|
||
esp8266.print(response);
|
||
|
||
if (waitFor("SEND OK", 5000)) {
|
||
Serial.println("Response sent to client.");
|
||
} else {
|
||
Serial.println("SEND OK not received (timeout).");
|
||
}
|
||
} else {
|
||
Serial.println("CIPSEND prompt not received (timeout).");
|
||
}
|
||
|
||
// بستن کانکشن
|
||
String closeCmd = "AT+CIPCLOSE=" + String(linkId);
|
||
sendCommand(closeCmd, "OK", 2000);
|
||
}
|
||
|
||
// استخراج linkId و len از خط +IPD
|
||
int parseIPDLine(const String& line, int &lenOut) {
|
||
int ipdPos = line.indexOf("+IPD,");
|
||
if (ipdPos == -1) return -1;
|
||
|
||
int firstComma = line.indexOf(',', ipdPos + 4);
|
||
int secondComma = line.indexOf(',', firstComma + 1);
|
||
if (firstComma == -1 || secondComma == -1) return -1;
|
||
|
||
int colon = line.indexOf(':', secondComma + 1);
|
||
if (colon == -1) {
|
||
lenOut = line.substring(secondComma + 1).toInt();
|
||
return line.substring(ipdPos + 4, firstComma).toInt();
|
||
} else {
|
||
lenOut = line.substring(firstComma + 1, secondComma).toInt();
|
||
return line.substring(ipdPos + 4, firstComma).toInt();
|
||
}
|
||
}
|
||
|
||
// پاکسازی payload بعد از +IPD
|
||
void drainPayload(int len) {
|
||
unsigned long t0 = millis();
|
||
int remaining = len;
|
||
while (millis() - t0 < 1000 && remaining > 0) {
|
||
if (esp8266.available()) {
|
||
esp8266.read();
|
||
remaining--;
|
||
}
|
||
}
|
||
}
|
||
|
||
// ارسال فرمان AT و انتظار ACK
|
||
bool sendCommand(const String& cmd, const char* ack, unsigned long timeout) {
|
||
esp8266.println(cmd);
|
||
return waitFor(ack, timeout);
|
||
}
|
||
|
||
// منتظر بودن برای وجود یک ACK/کلمه کلیدی تا مهلت معین
|
||
bool waitFor(const char* target, unsigned long timeout) {
|
||
unsigned long start = millis();
|
||
String buffer = "";
|
||
while (millis() - start < timeout) {
|
||
while (esp8266.available()) {
|
||
char c = esp8266.read();
|
||
buffer += c;
|
||
if (buffer.indexOf(target) != -1) return true;
|
||
}
|
||
}
|
||
Serial.print("Timeout waiting for: "); Serial.println(target);
|
||
return false;
|
||
}
|