212 lines
4.8 KiB
C++
212 lines
4.8 KiB
C++
#include <SoftwareSerial.h>
|
|
#include <Wire.h>
|
|
#include "RTClib.h"
|
|
#include <SPI.h>
|
|
#include <SD.h>
|
|
|
|
// تعریف نام مستعار برای حل مشکل تداخل
|
|
using SDLibFile = File;
|
|
|
|
SoftwareSerial espSerial(4, 5);
|
|
const int chipSelect = 10;
|
|
RTC_DS3231 rtc;
|
|
|
|
// کاهش مصرف حافظه با استفاده از PROGMEM
|
|
const char daysOfTheWeek[7][4] PROGMEM = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
|
|
|
// پیشتعریف توابع
|
|
bool saveDataToFile(const char* filename, const char* data, bool append = true);
|
|
bool formatSDCard();
|
|
void sendCommand(const char* cmd, int delayTime);
|
|
void sendHTTPResponse(int connectionId, const char* content);
|
|
const char* readSensorData();
|
|
const char* handleSaveData(const char* query);
|
|
const char* handleReadData(const char* query);
|
|
const char* handleFormatCard();
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
|
|
// راه اندازی کارت SD
|
|
if (!SD.begin(chipSelect)) {
|
|
Serial.println(F("SD Card Error!"));
|
|
} else {
|
|
Serial.println(F("SD Card OK"));
|
|
}
|
|
|
|
espSerial.begin(9600);
|
|
|
|
// راه اندازی RTC
|
|
if (!rtc.begin()) {
|
|
Serial.println(F("RTC Error!"));
|
|
while (1);
|
|
}
|
|
|
|
if (rtc.lostPower()) {
|
|
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
|
|
}
|
|
|
|
delay(1000);
|
|
Serial.println(F("Initializing ESP..."));
|
|
|
|
// کاهش دستورات ESP
|
|
const char* commands[] = {
|
|
"AT", "AT+RST", "AT+CWMODE=2",
|
|
"AT+CWSAP=\"ESP_CTRL\",\"12345678\",1,3",
|
|
"AT+CIPMUX=1", "AT+CIPSERVER=1,80"
|
|
};
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
sendCommand(commands[i], 1000);
|
|
}
|
|
|
|
Serial.println(F("AP Ready!"));
|
|
}
|
|
|
|
void loop() {
|
|
checkESP();
|
|
delay(1000);
|
|
}
|
|
|
|
void sendCommand(const char* cmd, int delayTime) {
|
|
Serial.print(F("Sending: "));
|
|
Serial.println(cmd);
|
|
espSerial.println(cmd);
|
|
|
|
delay(delayTime);
|
|
}
|
|
|
|
void sendHTTPResponse(int connectionId, const char* content) {
|
|
char response[512];
|
|
snprintf(response, sizeof(response),
|
|
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n%s",
|
|
content);
|
|
|
|
char cmd[50];
|
|
snprintf(cmd, sizeof(cmd), "AT+CIPSEND=%d,%d", connectionId, strlen(response));
|
|
|
|
sendCommand(cmd, 50);
|
|
sendCommand(response, 100);
|
|
|
|
snprintf(cmd, sizeof(cmd), "AT+CIPCLOSE=%d", connectionId);
|
|
sendCommand(cmd, 50);
|
|
}
|
|
|
|
void checkESP() {
|
|
static char buffer[128];
|
|
static int index = 0;
|
|
|
|
while (espSerial.available()) {
|
|
char c = espSerial.read();
|
|
if (index < sizeof(buffer) - 1) {
|
|
buffer[index++] = c;
|
|
}
|
|
|
|
if (c == '\n') {
|
|
buffer[index] = '\0';
|
|
|
|
if (strstr(buffer, "+IPD") != NULL) {
|
|
int connId = atoi(&buffer[5]);
|
|
handleRequest(connId, buffer);
|
|
}
|
|
|
|
index = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void handleRequest(int connectionId, char* request) {
|
|
char* getStart = strstr(request, "GET /");
|
|
if (!getStart) return;
|
|
|
|
char* pathStart = getStart + 5;
|
|
char* pathEnd = strchr(pathStart, ' ');
|
|
if (!pathEnd) return;
|
|
|
|
char path[32] = {0};
|
|
strncpy(path, pathStart, min((int)(pathEnd - pathStart), 31));
|
|
|
|
char* query = strchr(path, '?');
|
|
if (query) {
|
|
*query = '\0';
|
|
query++;
|
|
}
|
|
|
|
Serial.print(F("Path: "));
|
|
Serial.println(path);
|
|
|
|
const char* response;
|
|
|
|
if (strcmp(path, "se") == 0) {
|
|
response = readSensorData();
|
|
}
|
|
else if (strcmp(path, "save") == 0) {
|
|
response = handleSaveData(query);
|
|
}
|
|
else if (strcmp(path, "format") == 0) {
|
|
response = handleFormatCard();
|
|
}
|
|
else {
|
|
response = "Available endpoints: /se, /save, /format";
|
|
}
|
|
|
|
sendHTTPResponse(connectionId, response);
|
|
}
|
|
|
|
const char* readSensorData() {
|
|
static char buffer[64];
|
|
DateTime now = rtc.now();
|
|
|
|
snprintf(buffer, sizeof(buffer), "Temp: %.1fC, Time: %02d:%02d:%02d",
|
|
rtc.getTemperature(), now.hour(), now.minute(), now.second());
|
|
|
|
return buffer;
|
|
}
|
|
|
|
const char* handleSaveData(const char* query) {
|
|
if (query && strlen(query) > 0) {
|
|
if (saveDataToFile("data.txt", query, true)) {
|
|
return "Data saved";
|
|
}
|
|
return "Save error";
|
|
}
|
|
return "No data";
|
|
}
|
|
|
|
const char* handleFormatCard() {
|
|
return formatSDCard() ? "Formatted" : "Format error";
|
|
}
|
|
|
|
bool saveDataToFile(const char* filename, const char* data, bool append) {
|
|
SDLibFile dataFile;
|
|
|
|
if (append) {
|
|
dataFile = SD.open(filename, FILE_WRITE);
|
|
} else {
|
|
if (SD.exists(filename)) {
|
|
SD.remove(filename);
|
|
}
|
|
dataFile = SD.open(filename, FILE_WRITE);
|
|
}
|
|
|
|
if (!dataFile) return false;
|
|
|
|
bool result = dataFile.println(data);
|
|
dataFile.close();
|
|
|
|
return result;
|
|
}
|
|
|
|
bool formatSDCard() {
|
|
// فقط حذف فایلهای اصلی
|
|
const char* files[] = {"data.txt", "test.txt"};
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (SD.exists(files[i])) {
|
|
SD.remove(files[i]);
|
|
}
|
|
}
|
|
|
|
// تست نوشتن
|
|
return saveDataToFile("test.txt", "Formatted", false);
|
|
} |