I'm having trouble keeping saved settings on an esp8266. Every time I disconnect the esp from the power and reconnect it, the temperature and time variables are erased.
In the first sketch, I recorded the data in a txt file:
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include "LittleFS.h"
#include <Arduino_JSON.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "secrets.h"
#include "defs.h"
const char* ssid = STASSID;
const char* pass = STAPSK;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
// Json Variable to Hold Sensor Readings
JSONVar readings;
// Sensor de temperatura conectado na GPIO 4 / D2
#define ONE_WIRE_BUS 4
// Pinos do relê
#define HEATER_RELAY_PIN D1
#define COOLER_RELAY_PIN D0
// Hysteresis da temperatura
#define HYSTERESIS 0.4
// Sensor de temperatura
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Function prototype declaration
unsigned long countElapsedTime();
// Função auxiliar para converter float em string com determinada precisão
String floatToString(float value, int precision) {
char buffer[20];
sprintf(buffer, "%.*f", precision, value);
return String(buffer);
}
// Initialize WiFi
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
Serial.print("Conectando ao WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println("Conectado!");
Serial.println(WiFi.localIP());
}
// Carregar dados de temperatura do arquivo
void loadTemperatureData() {
if (LittleFS.exists("/temperatures.txt")) {
File file = LittleFS.open("/temperatures.txt", "r");
if (file) {
numTemperatures = 0;
while (file.available() && numTemperatures < max_temperatures) {
String line = file.readStringUntil('\n');
int separatorIndex1 = line.indexOf(',');
int separatorIndex2 = line.indexOf(',', separatorIndex1 + 1);
if (separatorIndex1 != -1 && separatorIndex2 != -1) {
temperatureData[numTemperatures].index = line.substring(0, separatorIndex1).toInt();
temperatureData[numTemperatures].temperature = line.substring(separatorIndex1 + 1, separatorIndex2).toFloat();
temperatureData[numTemperatures].time = line.substring(separatorIndex2 + 1).toInt();
numTemperatures++;
}
}
file.close();
}
}
}
// Salvar dados de temperatura em arquivo
void saveTemperatureData() {
File file = LittleFS.open("/temperatures.txt", "w");
if (file) {
for (int i = 0; i < numTemperatures; i++) {
file.println(temperatureData[i].index + "," + floatToString(temperatureData[i].temperature, 2) + "," + String(temperatureData[i].time));
}
file.flush(); // Certifica-se de que os dados são gravados na memória flash
file.close();
}
}
// Função para ler a temperatura com tratamento de erro
float readTemperature() {
sensors.requestTemperatures();
float temperature = sensors.getTempCByIndex(0);
if (temperature == DEVICE_DISCONNECTED_C || temperature == 85.0) {
Serial.println("Falha na leitura do sensor de temperatura");
}
return temperature;
}
// Initialização dos relays
void initializeRelays() {
pinMode(HEATER_RELAY_PIN, OUTPUT);
digitalWrite(HEATER_RELAY_PIN, LOW);
pinMode(COOLER_RELAY_PIN, OUTPUT);
digitalWrite(COOLER_RELAY_PIN, LOW);
}
// Controle dos relays baseado na temperatura corrente e temperatura alvo
void controlRelays(float currentTemperature, float targetTemperature) {
if (currentTemperature < targetTemperature - HYSTERESIS) {
digitalWrite(HEATER_RELAY_PIN, HIGH);
heaterState = true;
Serial.println("Aquecedor ligado");
coolerHeater = 2;
}
if (coolerState == false && currentTemperature > targetTemperature + HYSTERESIS) {
digitalWrite(COOLER_RELAY_PIN, HIGH);
coolerState = true; // Define a variável como true para evitar ligar a geladeira repetidamente
Serial.println("Geladeira ligada");
coolerHeater = 3;
}
if (targetTemperature - HYSTERESIS <= currentTemperature && currentTemperature <= targetTemperature + HYSTERESIS && coolerState) {
digitalWrite(COOLER_RELAY_PIN, LOW);
lastCoolerOffTime = millis();
Serial.println("Geladeira desligada");
coolerHeater = 4;
}
// Verifica se já passou o tempo de espera após desligar a geladeira
if (coolerState && millis() - lastCoolerOffTime >= 5 * 60 * 1000) {
coolerState = false; // Define a variável como false para permitir ligar a geladeira novamente no futuro
}
if (targetTemperature - HYSTERESIS <= currentTemperature && currentTemperature <= targetTemperature + HYSTERESIS && heaterState) {
digitalWrite(HEATER_RELAY_PIN, LOW);
heaterState = false;
Serial.println("Aquecedor desligado");
coolerHeater = 4;
}
}
// Verifica se o processo de fermentatação está completo
bool isFermentationComplete() {
return currentTemperatureIndex == numTemperatures;
}
void convertTime(unsigned long timeInSeconds, unsigned int &days, unsigned int &hours, unsigned int &minutes, unsigned int &seconds) {
days = timeInSeconds / 86400;
timeInSeconds %= 86400;
hours = timeInSeconds / 3600;
timeInSeconds %= 3600;
minutes = timeInSeconds / 60;
seconds = timeInSeconds % 60;
}
unsigned long countElapsedTime() {
if (contagemTempo) {
unsigned long tempo = millis() / 1000 - tempoAtual;
return tempo >= targetTime ? 0 : targetTime - tempo;
} else {
return 0;
}
}
// Função para configurar o servidor web
void configureWebServer() {
// Rota para a página inicial (index)
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
// Montar a página HTML dinamicamente com os dados de temperatura
String html;
File file = LittleFS.open("/index.html", "r");
if (file) {
html = file.readString();
file.close();
// RECEBE DADOS DE UM JS
request->send(200, "text/html", html);
} else {
// Erro ao abrir o arquivo
request->send(404, "text/plain", "Arquivo index.html não encontrado");
}
});
// Rota para tratar as requisições AJAX da página cadastro.html
server.on("/temperatureDataAjax", HTTP_GET, [](AsyncWebServerRequest *request) {
// Criar um objeto JSON com os dados necessários
DynamicJsonDocument json(256); // Tamanho da memória alocada para o JSON
if (numTemperatures > 0) {
json["temperatures"] = JsonArray();
for (int i = 0; i < numTemperatures; i++) {
JsonObject data = json["temperatures"].createNestedObject();
data["temperature"] = temperatureData[i].temperature;
data["time"] = temperatureData[i].time;
}
} else {
json["temperatures"] = nullptr;
}
String jsonResponse;
serializeJson(json, jsonResponse);
// Enviar a resposta JSON para a página cadastro.html
request->send(200, "application/json", jsonResponse);
});
// Rota para o tratamento de atualização da temperatura
server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request) {
int index = request->arg("index").toInt();
float newTemperature = request->arg("temperature").toFloat();
int newTime = request->arg("time").toInt();
newTime = newTime * 3600;
String html;
if (index >= 0 && index < numTemperatures) {
temperatureData[index].temperature = newTemperature;
temperatureData[index].time = newTime;
saveTemperatureData();
// Adiciona o cabeçalho de redirecionamento
request->send(200, "text/html", "<script>window.location.href = '/cadastro.html';</script>");
// Envia a resposta com o código de status 303 (See Other)
request->send(303);
} else {
request->send(404, "text/plain", "Índice inválido");
}
});
// Rota para o tratamento de adicionar nova temperatura/tempo
server.on("/add", HTTP_POST, [](AsyncWebServerRequest *request) {
float temperature = request->arg("temperature").toFloat();
unsigned long time = request->arg("time").toInt();
time = time * 3600;
if (numTemperatures < max_temperatures) {
temperatureData[numTemperatures].index = numTemperatures + 1; // Novo índice
temperatureData[numTemperatures].temperature = temperature;
temperatureData[numTemperatures].time = time;
numTemperatures++;
saveTemperatureData();
}
request->send(200, "text/html", "<script>window.location.href = '/cadastro.html';</script>");
});
// Rota para o tratamento de deletar temperatura/tempo
server.on("/delete", HTTP_GET, [](AsyncWebServerRequest *request) {
int index = request->arg("index").toInt();
Serial.print("Deletar o cadastro: ");
Serial.println(index);
if (index >= 0 && index < numTemperatures) {
for (int i = index; i < numTemperatures - 1; i++) {
temperatureData[i] = temperatureData[i + 1];
}
numTemperatures--;
saveTemperatureData();
}
request->send(200, "text/plain", "/");
request->send(303);
});
// Rota para o tratamento de iniciar a fermentação
server.on("/start", HTTP_GET, [](AsyncWebServerRequest *request) {
fermentationStarted = true;
Serial.println("Fermentação Iniciada");
request->send(200, "text/plain", "Fermentação Iniciada");
});
// Rota para o tratamento de enviar dados de temperatura/tempo
server.on("/temperatureData", HTTP_GET, [](AsyncWebServerRequest *request) {
if (currentTemperatureIndex >= 0 && currentTemperatureIndex < numTemperatures) {
targetTemperature = temperatureData[currentTemperatureIndex].temperature;
targetTime = temperatureData[currentTemperatureIndex].time;
} else {
// Tratar o índice inválido (caso necessário)
// Por exemplo, definir targetTime como 0 ou tomar outra ação apropriada
targetTemperature = 0;
targetTime = 0;
}
// Log para o monitor serial
remainingTime = countElapsedTime(); // Calculate the elapsed time
// Converta o tempo decorrido em uma string formatada (dias (dias) hh:mm:ss)
unsigned int days, hours, minutes, seconds;
convertTime(remainingTime, days, hours, minutes, seconds);
String formattedElapsedTime = String(days) + " (dias) " +
(hours < 10 ? "0" + String(hours) : String(hours)) + ":" +
(minutes < 10 ? "0" + String(minutes) : String(minutes)) + ":" +
(seconds < 10 ? "0" + String(seconds) : String(seconds));
// Converta o tempo alvo em uma string formatada (dias (dias) hh:mm:ss)
convertTime(targetTime, days, hours, minutes, seconds);
String formattedTargetTime = String(days) + " (dias) " +
(hours < 10 ? "0" + String(hours) : String(hours)) + ":" +
(minutes < 10 ? "0" + String(minutes) : String(minutes)) + ":" +
(seconds < 10 ? "0" + String(seconds) : String(seconds));
// Criar resposta JSON
String jsonResponse = "{";
jsonResponse += "\"targetTemperature\": " + String(targetTemperature, 2) + ",";
jsonResponse += "\"formattedTargetTime\": \"" + formattedTargetTime + "\",";
jsonResponse += "\"formattedElapsedTime\": \"" + formattedElapsedTime + "\",";
jsonResponse += "\"currentPhase\": " + String(currentPhase) + ",";
jsonResponse += "\"totalPhases\": " + String(totalPhases);
jsonResponse += "}";
request->send(200, "application/json", jsonResponse);
});
}
void setup() {
Serial.begin(115200);
initWiFi();
// Inicializa o sensor de temperatura
sensors.begin();
if (!LittleFS.begin()) {
Serial.println("An error has occurred while mounting LittleFS");
return;
}
// Configuração do servidor web
configureWebServer();
server.addHandler(&ws);
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len) {
// Não é necessário implementar nada aqui, pois o envio de dados é tratado em notifyClients()
});
// Iniciar o servidor web
server.begin();
// Lê o arquivo de temperatura/tempo
loadTemperatureData();
// Inicializa os relays
initializeRelays();
// Seta o currentTemperatureIndex para 0 inicialmente
currentTemperatureIndex = 0;
// Web Server Root URL
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(LittleFS, "/index.html", "text/html");
});
server.serveStatic("/", LittleFS, "/");
}
void notifyClients();
void loop() {
// Lê a temperatura atual
currentTemperature = readTemperature();
// Serial.println(currentTemperature);
if ((millis() - lastTime) > timerDelay) {
notifyClients();
}
if (numTemperatures > 0) {
totalPhases = numTemperatures;
currentPhase = currentTemperatureIndex + 1;
}
// Controla o início e término da fermentação
if (isFermentationComplete()) {
Serial.println("Fermentação completa");
fermentationInProgress = 3;
// Enviar mensagem de "Fermentação Concluída" através do WebSocket
ws.textAll("Fermentação Concluída");
// Reiniciar as variáveis de controle da fase
currentPhase = 1;
totalPhases = 0;
} else if (fermentationStarted && currentTemperatureIndex < numTemperatures) {
fermentationInProgress = 2;
// Enviar mensagem de "Fermentação Iniciada" através do WebSocket
ws.textAll("Fermentação Iniciada");
Serial.println("Fermentação Iniciada");
float targetTemperature = temperatureData[currentTemperatureIndex].temperature;
controlRelays(currentTemperature, targetTemperature);
if (contagemTempo == false && currentTemperature >= targetTemperature - HYSTERESIS && currentTemperature <= targetTemperature + HYSTERESIS) {
Serial.println("Temperatura alvo atingida! Início da contagem do tempo!");
atualizaTarget = true;
}
if (atualizaTarget == true) {
tempoAtual = millis() / 1000;
tempoFase = tempoAtual + targetTime;
atualizaTarget = false;
contagemTempo = true;
}
if (tempoFase < (millis() / 1000) && contagemTempo == true) {
Serial.println("Tempo no alvo alcançado. Passando para a próxima etapa!");
currentTemperatureIndex++;
contagemTempo = false;
}
} else {
fermentationInProgress = false;
// Enviar mensagem de "Aguardando Início" através do WebSocket
ws.textAll("Aguardando Início");
}
}
void notifyClients() {
// Cria um objeto JSON para armazenar o valor do sensor
DynamicJsonDocument json(256); // Tamanho da memória alocada para o JSON
// Converte o valor do sensor para uma string com 2 casas decimais
String sensorValueStr = String(currentTemperature, 2);
// Adiciona o valor do sensor ao objeto JSON
json["sensor"] = sensorValueStr;
// Define o status da fermentação com base na variável fermentationInProgress
if (fermentationInProgress == 1) {
json["status"] = "Aguardando Início";
} else if (fermentationInProgress == 2) {
json["status"] = "Fermentação Iniciada";
} else if (fermentationInProgress == 3) {
json["status"] = "Fermentação Concluída";
}
// Informa ao cliente se cooler ou heatear estão ligados
if (coolerHeater == 1) {
json["coolerHeater"] = "1";
} else if (coolerHeater == 2) {
json["coolerHeater"] = "2";
} else if (coolerHeater == 3) {
json["coolerHeater"] = "3";
} else if (coolerHeater == 4) {
json["coolerHeater"] = "4";
}
// Serializa o JSON para uma string
String jsonStr;
serializeJson(json, jsonStr);
// Envia a string JSON para todos os clientes conectados via WebSocket
ws.textAll(jsonStr);
}
Agora, estou gravando os dados na EEPROM e mesmo assim ainda estão sendo apagados
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include "LittleFS.h"
#include <EEPROM.h>
#include <Arduino_JSON.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "secrets.h"
#include "defs.h"
#include <EEPROM.h>
const char* ssid = STASSID;
const char* pass = STAPSK;
// Tamanho da estrutura em bytes (9 bytes por entrada)
#define STRUCT_SIZE 9
// Número máximo de temperaturas a serem armazenadas
#define max_temperatures 20
TemperatureData temperatureData[max_temperatures];
#define EEPROM_SIZE sizeof(temperatureData)
#define EEPROM_ADDR 0 // Armazenando no início da EEPROM (endereço 0)
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
// Json Variable to Hold Sensor Readings
JSONVar readings;
// Sensor de temperatura conectado na GPIO 4 / D2
#define ONE_WIRE_BUS 4
// Pinos do relê
#define HEATER_RELAY_PIN D1
#define COOLER_RELAY_PIN D0
// Hysteresis da temperatura
#define HYSTERESIS 0.4
// Sensor de temperatura
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Function prototype declaration
unsigned long countElapsedTime();
// Função auxiliar para converter float em string com determinada precisão
String floatToString(float value, int precision) {
char buffer[20];
sprintf(buffer, "%.*f", precision, value);
return String(buffer);
}
// Initialize WiFi
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
Serial.print("Conectando ao WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println("Conectado!");
Serial.println(WiFi.localIP());
}
// Função para ler os dados da EEPROM e carregar na estrutura temperatureData
void loadTemperatureData() {
int addr = 0;
for (int i = 0; i < max_temperatures; i++) {
byte index = EEPROM.read(addr++);
float temperature;
EEPROM.get(addr, temperature);
addr += sizeof(float);
unsigned long time;
EEPROM.get(addr, time);
addr += sizeof(unsigned long);
if (index == 0xFF || isnan(temperature) || time == 0xFFFFFFFF) {
// Dado inválido ou espaço não utilizado na EEPROM
break;
}
temperatureData[i].index = index;
temperatureData[i].temperature = temperature;
temperatureData[i].time = time;
}
}
// Função para salvar os dados da estrutura temperatureData na EEPROM
void saveTemperatureData() {
int addr = 0;
for (int i = 0; i < max_temperatures; i++) {
if (temperatureData[i].index == 0xFF || isnan(temperatureData[i].temperature) || temperatureData[i].time == 0xFFFFFFFF) {
// Dado inválido ou espaço não utilizado na estrutura
break;
}
EEPROM.write(addr++, temperatureData[i].index);
EEPROM.put(addr, temperatureData[i].temperature);
addr += sizeof(float);
EEPROM.put(addr, temperatureData[i].time);
addr += sizeof(unsigned long);
}
EEPROM.commit();
}
// Função para ler a temperatura com tratamento de erro
float readTemperature() {
sensors.requestTemperatures();
float temperature = sensors.getTempCByIndex(0);
if (temperature == DEVICE_DISCONNECTED_C || temperature == 85.0) {
Serial.println("Falha na leitura do sensor de temperatura");
}
return temperature;
}
// Initialização dos relays
void initializeRelays() {
pinMode(HEATER_RELAY_PIN, OUTPUT);
digitalWrite(HEATER_RELAY_PIN, LOW);
pinMode(COOLER_RELAY_PIN, OUTPUT);
digitalWrite(COOLER_RELAY_PIN, LOW);
}
// Controle dos relays baseado na temperatura corrente e temperatura alvo
void controlRelays(float currentTemperature, float targetTemperature) {
if (currentTemperature < targetTemperature - HYSTERESIS) {
digitalWrite(HEATER_RELAY_PIN, HIGH);
heaterState = true;
Serial.println("Aquecedor ligado");
coolerHeater = 2;
}
if (coolerState == false && currentTemperature > targetTemperature + HYSTERESIS) {
digitalWrite(COOLER_RELAY_PIN, HIGH);
coolerState = true; // Define a variável como true para evitar ligar a geladeira repetidamente
Serial.println("Geladeira ligada");
coolerHeater = 3;
}
if (targetTemperature - HYSTERESIS <= currentTemperature && currentTemperature <= targetTemperature + HYSTERESIS && coolerState) {
digitalWrite(COOLER_RELAY_PIN, LOW);
lastCoolerOffTime = millis();
Serial.println("Geladeira desligada");
coolerHeater = 4;
}
// Verifica se já passou o tempo de espera após desligar a geladeira
if (coolerState && millis() - lastCoolerOffTime >= 5 * 60 * 1000) {
coolerState = false; // Define a variável como false para permitir ligar a geladeira novamente no futuro
}
if (targetTemperature - HYSTERESIS <= currentTemperature && currentTemperature <= targetTemperature + HYSTERESIS && heaterState) {
digitalWrite(HEATER_RELAY_PIN, LOW);
heaterState = false;
Serial.println("Aquecedor desligado");
coolerHeater = 4;
}
}
// Verifica se o processo de fermentatação está completo
bool isFermentationComplete() {
return currentTemperatureIndex == numTemperatures;
}
void convertTime(unsigned long timeInSeconds, unsigned int &days, unsigned int &hours, unsigned int &minutes, unsigned int &seconds) {
days = timeInSeconds / 86400;
timeInSeconds %= 86400;
hours = timeInSeconds / 3600;
timeInSeconds %= 3600;
minutes = timeInSeconds / 60;
seconds = timeInSeconds % 60;
}
unsigned long countElapsedTime() {
if (contagemTempo) {
unsigned long tempo = millis() / 1000 - tempoAtual;
return tempo >= targetTime ? 0 : targetTime - tempo;
} else {
return 0;
}
}
// Função para configurar o servidor web
void configureWebServer() {
// Rota para a página inicial (index)
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
// Montar a página HTML dinamicamente com os dados de temperatura
String html;
File file = LittleFS.open("/index.html", "r");
if (file) {
html = file.readString();
file.close();
// RECEBE DADOS DE UM JS
request->send(200, "text/html", html);
} else {
// Erro ao abrir o arquivo
request->send(404, "text/plain", "Arquivo index.html não encontrado");
}
});
// Rota para tratar as requisições AJAX da página cadastro.html
server.on("/temperatureDataAjax", HTTP_GET, [](AsyncWebServerRequest *request) {
// Criar um objeto JSON com os dados necessários
DynamicJsonDocument json(256); // Tamanho da memória alocada para o JSON
if (numTemperatures > 0) {
json["temperatures"] = JsonArray();
for (int i = 0; i < numTemperatures; i++) {
JsonObject data = json["temperatures"].createNestedObject();
data["temperature"] = temperatureData[i].temperature;
data["time"] = temperatureData[i].time;
}
} else {
json["temperatures"] = nullptr;
}
String jsonResponse;
serializeJson(json, jsonResponse);
// Enviar a resposta JSON para a página cadastro.html
request->send(200, "application/json", jsonResponse);
});
// Rota para o tratamento de atualização da temperatura
server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request) {
int index = request->arg("index").toInt();
float newTemperature = request->arg("temperature").toFloat();
int newTime = request->arg("time").toInt();
newTime = newTime * 3600;
String html;
if (index >= 0 && index < numTemperatures) {
temperatureData[index].temperature = newTemperature;
temperatureData[index].time = newTime;
saveTemperatureData();
// Adiciona o cabeçalho de redirecionamento
request->send(200, "text/html", "<script>window.location.href = '/cadastro.html';</script>");
// Envia a resposta com o código de status 303 (See Other)
request->send(303);
} else {
request->send(404, "text/plain", "Índice inválido");
}
});
// Rota para o tratamento de adicionar nova temperatura/tempo
server.on("/add", HTTP_POST, [](AsyncWebServerRequest *request) {
float temperature = request->arg("temperature").toFloat();
unsigned long time = request->arg("time").toInt();
time = time * 3600;
if (numTemperatures < max_temperatures) {
temperatureData[numTemperatures].index = numTemperatures + 1; // Novo índice
temperatureData[numTemperatures].temperature = temperature;
temperatureData[numTemperatures].time = time;
numTemperatures++;
saveTemperatureData();
}
request->send(200, "text/html", "<script>window.location.href = '/cadastro.html';</script>");
});
// Rota para o tratamento de deletar temperatura/tempo
server.on("/delete", HTTP_GET, [](AsyncWebServerRequest *request) {
int index = request->arg("index").toInt();
Serial.print("Deletar o cadastro: ");
Serial.println(index);
if (index >= 0 && index < numTemperatures) {
for (int i = index; i < numTemperatures - 1; i++) {
temperatureData[i] = temperatureData[i + 1];
}
numTemperatures--;
saveTemperatureData();
}
request->send(200, "text/plain", "/");
request->send(303);
});
// Rota para o tratamento de iniciar a fermentação
server.on("/start", HTTP_GET, [](AsyncWebServerRequest *request) {
fermentationStarted = true;
Serial.println("Fermentação Iniciada");
request->send(200, "text/plain", "Fermentação Iniciada");
});
// Rota para o tratamento de enviar dados de temperatura/tempo
server.on("/temperatureData", HTTP_GET, [](AsyncWebServerRequest *request) {
if (currentTemperatureIndex >= 0 && currentTemperatureIndex < numTemperatures) {
targetTemperature = temperatureData[currentTemperatureIndex].temperature;
targetTime = temperatureData[currentTemperatureIndex].time;
} else {
// Tratar o índice inválido (caso necessário)
// Por exemplo, definir targetTime como 0 ou tomar outra ação apropriada
targetTemperature = 0;
targetTime = 0;
}
// Log para o monitor serial
remainingTime = countElapsedTime(); // Calculate the elapsed time
// Converta o tempo decorrido em uma string formatada (dias (dias) hh:mm:ss)
unsigned int days, hours, minutes, seconds;
convertTime(remainingTime, days, hours, minutes, seconds);
String formattedElapsedTime = String(days) + " (dias) " +
(hours < 10 ? "0" + String(hours) : String(hours)) + ":" +
(minutes < 10 ? "0" + String(minutes) : String(minutes)) + ":" +
(seconds < 10 ? "0" + String(seconds) : String(seconds));
// Converta o tempo alvo em uma string formatada (dias (dias) hh:mm:ss)
convertTime(targetTime, days, hours, minutes, seconds);
String formattedTargetTime = String(days) + " (dias) " +
(hours < 10 ? "0" + String(hours) : String(hours)) + ":" +
(minutes < 10 ? "0" + String(minutes) : String(minutes)) + ":" +
(seconds < 10 ? "0" + String(seconds) : String(seconds));
// Criar resposta JSON
String jsonResponse = "{";
jsonResponse += "\"targetTemperature\": " + String(targetTemperature, 2) + ",";
jsonResponse += "\"formattedTargetTime\": \"" + formattedTargetTime + "\",";
jsonResponse += "\"formattedElapsedTime\": \"" + formattedElapsedTime + "\",";
jsonResponse += "\"currentPhase\": " + String(currentPhase) + ",";
jsonResponse += "\"totalPhases\": " + String(totalPhases);
jsonResponse += "}";
request->send(200, "application/json", jsonResponse);
});
}
void setup() {
Serial.begin(115200);
initWiFi();
// Inicializa o sensor de temperatura
sensors.begin();
if (!LittleFS.begin()) {
Serial.println("An error has occurred while mounting LittleFS");
return;
}
// Inicializa a EEPROM
EEPROM.begin(EEPROM_SIZE);
// Lê o arquivo de temperatura/tempo
loadTemperatureData();
// Configuração do servidor web
configureWebServer();
server.addHandler(&ws);
ws.onEvent([](AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len) {
// Não é necessário implementar nada aqui, pois o envio de dados é tratado em notifyClients()
});
// Iniciar o servidor web
server.begin();
// Inicializa os relays
initializeRelays();
// Seta o currentTemperatureIndex para 0 inicialmente
currentTemperatureIndex = 0;
// Web Server Root URL
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(LittleFS, "/index.html", "text/html");
});
server.serveStatic("/", LittleFS, "/");
}
void notifyClients();
void loop() {
// Lê a temperatura atual
currentTemperature = readTemperature();
// Serial.println(currentTemperature);
if ((millis() - lastTime) > timerDelay) {
notifyClients();
}
if (numTemperatures > 0) {
totalPhases = numTemperatures;
currentPhase = currentTemperatureIndex + 1;
}
// Controla o início e término da fermentação
if (isFermentationComplete()) {
Serial.println("Fermentação completa");
fermentationInProgress = 3;
// Enviar mensagem de "Fermentação Concluída" através do WebSocket
ws.textAll("Fermentação Concluída");
// Reiniciar as variáveis de controle da fase
currentPhase = 1;
totalPhases = 0;
} else if (fermentationStarted && currentTemperatureIndex < numTemperatures) {
fermentationInProgress = 2;
// Enviar mensagem de "Fermentação Iniciada" através do WebSocket
ws.textAll("Fermentação Iniciada");
Serial.println("Fermentação Iniciada");
float targetTemperature = temperatureData[currentTemperatureIndex].temperature;
controlRelays(currentTemperature, targetTemperature);
if (contagemTempo == false && currentTemperature >= targetTemperature - HYSTERESIS && currentTemperature <= targetTemperature + HYSTERESIS) {
Serial.println("Temperatura alvo atingida! Início da contagem do tempo!");
atualizaTarget = true;
}
if (atualizaTarget == true) {
tempoAtual = millis() / 1000;
tempoFase = tempoAtual + targetTime;
atualizaTarget = false;
contagemTempo = true;
}
if (tempoFase < (millis() / 1000) && contagemTempo == true) {
Serial.println("Tempo no alvo alcançado. Passando para a próxima etapa!");
currentTemperatureIndex++;
contagemTempo = false;
}
} else {
fermentationInProgress = false;
// Enviar mensagem de "Aguardando Início" através do WebSocket
ws.textAll("Aguardando Início");
}
}
void notifyClients() {
// Cria um objeto JSON para armazenar o valor do sensor
DynamicJsonDocument json(256); // Tamanho da memória alocada para o JSON
// Converte o valor do sensor para uma string com 2 casas decimais
String sensorValueStr = String(currentTemperature, 2);
// Adiciona o valor do sensor ao objeto JSON
json["sensor"] = sensorValueStr;
// Define o status da fermentação com base na variável fermentationInProgress
if (fermentationInProgress == 1) {
json["status"] = "Aguardando Início";
} else if (fermentationInProgress == 2) {
json["status"] = "Fermentação Iniciada";
} else if (fermentationInProgress == 3) {
json["status"] = "Fermentação Concluída";
}
// Informa ao cliente se cooler ou heatear estão ligados
if (coolerHeater == 1) {
json["coolerHeater"] = "1";
} else if (coolerHeater == 2) {
json["coolerHeater"] = "2";
} else if (coolerHeater == 3) {
json["coolerHeater"] = "3";
} else if (coolerHeater == 4) {
json["coolerHeater"] = "4";
}
// Serializa o JSON para uma string
String jsonStr;
serializeJson(json, jsonStr);
// Envia a string JSON para todos os clientes conectados via WebSocket
ws.textAll(jsonStr);
}
What could be wrong?