#include <Arduino.h>
#include <SPI.h>
// Inclusão do Globals (Configurações e Variáveis)
#include "Globals.h"
// Inclusão dos Módulos Orientados a Objetos
#include "Logger.h"
#include "RtcManager.h"
#include "NfcReader.h"
#include "Display.h"
#include "KeypadInput.h"
// ==============================================================================
// 1. ALOCAÇÃO DAS VARIÁVEIS GLOBAIS (Declaradas como extern no Globals.h)
// ==============================================================================
int totalUsuarios = 0;
int totalProdutos = 0;
Usuario dbUsuarios[MAX_USUARIOS];
Produto dbProdutos[MAX_PRODUTOS];
SystemState currentState = BOOT;
SystemState returnState = STANDBY;
String inputBuffer = "";
Usuario usuarioAtual;
Produto produtoAtual;
// Variáveis de Produção
int opNumero = 0;
int qtdePlanejada = 0;
int qtdeProduzida = 0;
int qtdeRefugo = 0;
int ciclosRealizados = 0;
// ==============================================================================
// 2. INSTANCIAÇÃO DOS MÓDULOS DE HARDWARE
// ==============================================================================
Logger sdCard(SD_CS);
RtcManager relogio;
NfcReader leitorNfc(RFID_SS, RFID_RST);
Display tela(0x27, 20, 4); // Endereço I2C, 20 colunas, 4 linhas
KeypadInput teclado;
// ==============================================================================
// 3. IMPLEMENTAÇÃO DAS FUNÇÕES GLOBAIS
// ==============================================================================
void setLEDs(bool red, bool green, bool blue) {
digitalWrite(LED_VERMELHO, red ? HIGH : LOW);
digitalWrite(LED_VERDE, green ? HIGH : LOW);
digitalWrite(LED_AMARELO, blue ? HIGH : LOW);
}
// ==============================================================================
// 4. SETUP - INICIALIZAÇÃO
// ==============================================================================
void setup() {
Serial.begin(115200);
// Configura os pinos de LEDs e Botões
pinMode(LED_VERDE, OUTPUT);
pinMode(LED_AMARELO, OUTPUT);
pinMode(LED_VERMELHO, OUTPUT);
pinMode(BTN_VERDE, INPUT_PULLUP);
pinMode(BTN_AMARELO, INPUT_PULLUP);
pinMode(BTN_VERMELHO, INPUT_PULLUP);
// Garante que os LEDs começam apagados
setLEDs(false, false, false);
// Inicializa o barramento SPI (para SD e RFID)
SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN);
// Inicializa a Tela primeiro para dar feedback visual
tela.iniciar();
tela.limpar();
tela.imprimir(0, 1, " INICIANDO AULE ");
tela.imprimir(0, 2, " SISTEMA MES... ");
// Inicializa os demais módulos
relogio.iniciar();
leitorNfc.iniciar();
teclado.iniciar();
// Inicializa SD e carrega as Listas (Usuarios e Produtos)
if (sdCard.iniciar()) {
sdCard.carregarUsuarios(dbUsuarios, MAX_USUARIOS, totalUsuarios);
sdCard.carregarProdutos(dbProdutos, MAX_PRODUTOS, totalProdutos);
} else {
tela.imprimir(0, 3, "ERRO NO CARTAO SD!");
delay(2000);
}
delay(1500); // Pausa dramática para ver a tela de boot
currentState = STANDBY;
}
// ==============================================================================
// 5. LOOP PRINCIPAL - A MÁQUINA DE ESTADOS
// ==============================================================================
void loop() {
// 1. Faz a leitura contínua dos sensores e relógio (NÃO BLOQUEANTE)
char tecla = teclado.lerTecla();
String tagLida = leitorNfc.lerTag();
String horaAtual = relogio.getHoraAtual();
// 2. Transições e Lógica de Negócios (O Cérebro)
switch (currentState) {
case STANDBY:
if (tecla == 'A') {
inputBuffer = "";
currentState = LOGIN;
}
// Se passou o crachá direto
if (tagLida != "") {
// Exemplo simplificado de login via NFC
for (int i = 0; i < totalUsuarios; i++) {
if (dbUsuarios[i].rfid == tagLida) {
usuarioAtual = dbUsuarios[i];
sdCard.registrar("Login NFC aprovado: " + usuarioAtual.nome, horaAtual);
currentState = WELCOME;
break;
}
}
}
break;
case LOGIN:
if (tecla >= '0' && tecla <= '9') {
inputBuffer += tecla;
tela.forcarAtualizacao();
} else if (tecla == '#') {
// Valida Login via Teclado
bool achou = false;
for (int i = 0; i < totalUsuarios; i++) {
if (dbUsuarios[i].matricula == inputBuffer) {
usuarioAtual = dbUsuarios[i];
sdCard.registrar("Login TECLADO aprovado: " + usuarioAtual.nome, horaAtual);
currentState = WELCOME;
achou = true;
break;
}
}
if (!achou) {
inputBuffer = ""; // Limpa se errou
tela.forcarAtualizacao();
}
} else if (tecla == '*') {
currentState = STANDBY;
}
break;
case WELCOME:
if (tecla == '2') {
inputBuffer = "";
currentState = NOVA_OP;
} else if (tecla == '*') {
currentState = STANDBY; // Logout
}
break;
case NOVA_OP:
// Simulação rápida para pular para Status Inicial
if (tecla == '#') {
opNumero = inputBuffer.toInt();
inputBuffer = "";
currentState = STATUS_INICIAL;
} else if (tecla >= '0' && tecla <= '9') {
inputBuffer += tecla;
tela.forcarAtualizacao();
}
break;
case STATUS_INICIAL:
if (tecla == '1') {
qtdeProduzida = 0;
currentState = PROD_CARROSSEL_1;
}
break;
case PROD_CARROSSEL_1:
// O botão verde avança a produção!
if (digitalRead(BTN_VERDE) == LOW) {
qtdeProduzida++;
sdCard.registrar("Ciclo finalizado. Peca=" + String(qtdeProduzida), horaAtual);
tela.forcarAtualizacao();
delay(300); // Debounce rústico para não contar 50x por segundo
}
if (tecla == '*') {
sdCard.registrar("Producao finalizada", horaAtual);
currentState = WELCOME;
}
break;
// Adicione os outros cases aqui de acordo com sua necessidade
default:
break;
}
// 3. Renderiza a tela de acordo com o estado atual
tela.atualizarTela(currentState, horaAtual, produtoAtual);
}