#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
// Configuração do LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Configuração WiFi para Wokwi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Configuração Redis para Wokwi
const char* redisServer = "127.0.0.1"; // Endereço especial para Wokwi
const int redisPort = 6379;
WiFiClient redisClient;
// Variáveis para controle
unsigned long lastUpdate = 0;
const long updateInterval = 3000; // 3 segundos
int displayPage = 0;
void setup() {
Serial.begin(115200);
// Inicializa LCD
lcd.init();
lcd.backlight();
lcd.print("Inicializando...");
// Conecta WiFi (obrigatório mesmo no Wokwi)
WiFi.begin(ssid, password);
int tentativas = 0;
while (WiFi.status() != WL_CONNECTED && tentativas < 10) {
delay(500);
Serial.print(".");
lcd.setCursor(0, 1);
lcd.print("Conectando WiFi");
tentativas++;
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\nFalha no WiFi");
lcd.clear();
lcd.print("Erro WiFi");
while(1); // Trava se não conectar
}
Serial.println("\nConectado WiFi!");
lcd.clear();
lcd.print("WiFi OK");
// Conexão com Redis
if (connectRedis()) {
lcd.setCursor(0, 1);
lcd.print("Redis OK");
} else {
lcd.setCursor(0, 1);
lcd.print("Redis Falhou");
while(1); // Trava se não conectar
}
delay(2000);
}
bool connectRedis() {
Serial.print("Conectando ao Redis...");
if (redisClient.connect(redisServer, redisPort)) {
Serial.println("Conectado!");
return true;
} else {
Serial.println("Falha!");
return false;
}
}
void loop() {
if (millis() - lastUpdate >= updateInterval) {
if (!redisClient.connected()) {
if (!connectRedis()) {
lcd.clear();
lcd.print("Reconectando...");
delay(1000);
return;
}
}
String latestData = getLatestRedisData();
if (latestData != "") {
processAndDisplayData(latestData);
}
lastUpdate = millis();
displayPage = (displayPage + 1) % 2;
}
}
String getLatestRedisData() {
// Envia comando para pegar o último timestamp
redisClient.println("LRANGE sensor:historico 0 0");
// Aguarda resposta
delay(50);
if (redisClient.available()) {
String response = redisClient.readStringUntil('\n');
if (response.startsWith("*1")) { // Resposta válida
// Pula as linhas de protocolo Redis
redisClient.readStringUntil('\n'); // Tamanho do item
String timestamp = redisClient.readStringUntil('\n'); // Valor real
timestamp.trim();
// Agora busca os dados do sensor
redisClient.println("HGETALL sensor:data:" + timestamp);
delay(50);
// Retorna toda a resposta para processamento
String sensorData = "";
while (redisClient.available()) {
sensorData += redisClient.readStringUntil('\n');
sensorData += "\n";
}
return sensorData;
}
}
return "";
}
void processAndDisplayData(String redisData) {
float temp = 0, dist = 0;
int lum = 0, gas = 0;
// Processa a resposta do Redis linha por linha
int lineCount = 0;
String field = "";
while (redisData.length() > 0) {
int newlinePos = redisData.indexOf('\n');
if (newlinePos == -1) break;
String line = redisData.substring(0, newlinePos);
line.trim();
redisData = redisData.substring(newlinePos + 1);
// Ignora linhas de protocolo Redis ($n)
if (line.startsWith("$") || line.startsWith("*")) continue;
if (lineCount % 2 == 0) {
field = line;
} else {
if (field == "temperatura") temp = line.toFloat();
else if (field == "distancia") dist = line.toFloat();
else if (field == "luminosidade") lum = line.toInt();
else if (field == "gas") gas = line.toInt();
}
lineCount++;
}
// Exibe no LCD
mostrarNoLCD(temp, dist, lum, gas);
}
void mostrarNoLCD(float temp, float dist, int lum, int gas) {
lcd.clear();
if (displayPage == 0) {
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temp, 1);
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("Dist: ");
lcd.print(dist, 1);
lcd.print("cm");
} else {
lcd.setCursor(0, 0);
lcd.print("Luz: ");
lcd.print(lum);
lcd.setCursor(0, 1);
lcd.print("Gas: ");
lcd.print(gas);
}
}