Biblioteca Arduino/ESP32 para gerenciamento não-bloqueante de WiFi e MQTT, com reconexão automática e fila de mensagens offline.
Autor: professorThiago Depende de: DebugManager — baixado automaticamente.
Por que não-bloqueante?
A abordagem tradicional usa while() para aguardar conexão:
// ❌ Bloqueante — trava o setup() por até 15 segundos
while (WiFi.status() != WL_CONNECTED) { delay(500); }
Esta biblioteca usa máquinas de estado processadas no loop():
// ✓ Não-bloqueante — setup() retorna imediatamente
conectividade.beginSimples(wifi, mqtt, topicos);
void loop() {
conectividade.update(); // avança sem travar
// sua lógica continua normalmente
}
Funcionalidades
- ✅ WiFi e MQTT não-bloqueantes com reconexão automática.
- ✅ Três modos de conexão: SIMPLES, TLS e AWS IoT Core.
- ✅ Fila offline: mensagens publicadas sem MQTT são salvas e enviadas ao reconectar.
- ✅ Sem dependência de
secrets.h— tudo configurado via structs nobegin(). - ✅ Diagnóstico detalhado: códigos WiFi e MQTT traduzidos com dicas de solução.
- ✅ Buffer MQTT configurável via
configurarBufferMQTT().
Instalação
lib_deps =
https://github.com/professorThiago/ESP32Connectivity
O PlatformIO baixa automaticamente DebugManager e PubSubClient.
Modos de conexão
| Modo | Enum | Quando usar |
|---|---|---|
| Sem criptografia | ModoConexao::SIMPLES |
Redes locais confiáveis, testes |
| TLS | ModoConexao::TLS |
Brokers públicos (HiveMQ, Mosquitto Cloud, etc.) |
| AWS IoT Core | ModoConexao::AWS_IOT |
AWS com certificado de dispositivo (mTLS) |
O modo é determinado pela sobrecarga do begin() chamada — não há flag booleana ou variável global.
Quick start
Modo SIMPLES
#include <DebugManager.h>
#include <ESP32Connectivity.h>
ConfigWiFi wifi = { "MinhaRede", "minha_senha" };
ConfigMQTT mqtt = { "192.168.1.100", 1883, "esp32_id", "", "" };
const char* pub[] = { "casa/status" };
const char* rec[] = { "casa/comando" };
ConfigTopicos topicos = { pub, 1, rec, 1 };
void setup() {
configurarDebug(DEBUG_INFO, 4);
conectividade.beginSimples(wifi, mqtt, topicos);
}
void loop() {
conectividade.update();
conectividade.publicar(0, "online");
delay(5000);
}
Modo TLS
const char meuCertCA[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
...certificado CA do broker...
-----END CERTIFICATE-----
)EOF";
ConfigMQTT mqtt = { "broker.hivemq.com", 8883, "esp32_id", "usuario", "senha" };
ConfigTLS tls = { meuCertCA };
conectividade.beginTLS(wifi, mqtt, tls, topicos);
Modo AWS IoT Core
const char awsCertCA[] PROGMEM = R"EOF( ...AmazonRootCA1... )EOF";
const char awsCertCRT[] PROGMEM = R"CRT( ...certificado do dispositivo... )CRT";
const char awsCertPrivate[] PROGMEM = R"KEY( ...chave privada... )KEY";
ConfigAWS aws = {
"xxxx.iot.us-east-1.amazonaws.com",
8883,
"meu_thing_name",
awsCertCA, awsCertCRT, awsCertPrivate
};
conectividade.beginAWS(wifi, aws, topicos);
Structs de configuração
ConfigWiFi
ConfigWiFi wifi = {
"SSID", // nome da rede
"SENHA" // senha
};
ConfigMQTT
ConfigMQTT mqtt = {
"broker.exemplo.com", // endereço do broker
8883, // porta (1883 sem TLS, 8883 com TLS)
"esp32_meu_projeto", // clientId — único por dispositivo
"usuario", // "" para conexão anônima
"senha" // "" para conexão anônima
};
ConfigTLS
ConfigTLS tls = {
meuCertCA // ponteiro para o certificado CA em PEM (PROGMEM)
};
Deixe certificadoCA = "" para usar setInsecure() — apenas para testes.
ConfigAWS
ConfigAWS aws = {
"xxxx.iot.us-east-1.amazonaws.com", // endpoint
8883, // porta
"meu_thing_name", // clientId
awsCertCA, // AmazonRootCA1.pem
awsCertCRT, // certificado do dispositivo
awsCertPrivate // chave privada
};
ConfigTopicos
const char* pub[] = { "projeto/status", "projeto/dados" };
const char* rec[] = { "projeto/comando" };
ConfigTopicos topicos = {
pub, 2, // array de publicação + quantidade
rec, 1 // array de recebimento + quantidade
};
API
Inicialização
// Modo SIMPLES
conectividade.beginSimples(wifi, mqtt, topicos);
// Modo TLS
conectividade.beginTLS(wifi, mqtt, tls, topicos);
// Modo AWS IoT
conectividade.beginAWS(wifi, aws, topicos);
Loop
conectividade.update(); // SEMPRE no loop() — nunca omita
Buffer MQTT (opcional, antes do begin)
// Aumenta o limite para payloads maiores que 256 bytes
conectividade.configurarBufferMQTT(1024);
conectividade.beginSimples(wifi, mqtt, topicos);
| Parâmetro | Padrão | Máximo recomendado |
|---|---|---|
| Buffer MQTT | 256 bytes | 4096 bytes no ESP32 |
Fila offline
Como funciona
Toda mensagem passa pela fila antes de ser enviada — mesmo quando o MQTT está conectado. Isso garante que nenhuma mensagem seja perdida em caso de queda de conexão entre a chamada a publicar() e o envio efetivo pelo TCP:
publicar("topico", "payload")
│
├── 1. Enfileira a mensagem (sempre)
│
└── 2. MQTT conectado?
├── Sim → tenta drenar a fila agora
│ ├── Envio ok → remove da fila → retorna true
│ └── Falhou → fica na fila → retorna false
└── Não → fica na fila até reconectar → retorna false
A fila é drenada automaticamente pelo update() a cada loop() quando a conexão é restabelecida.
// Publica — sempre enfileira antes de enviar
conectividade.publicar(0, "payload"); // por índice
conectividade.publicar("topico/x", "payload"); // por nome
// Consulta quantas mensagens estão aguardando
conectividade.mensagensNaFila(); // uint8_t
Configurando o tamanho da fila
O tamanho da fila é definido por #define em tempo de compilação. Declare os defines antes do #include <ESP32Connectivity.h> no main.cpp:
// ⚠ DEVE vir ANTES do #include
#define CONNECTIVITY_FILA_SLOTS 20 // número de mensagens (padrão: 10)
#define CONNECTIVITY_FILA_TOPICO_MAX 128 // bytes por tópico (padrão: 64)
#define CONNECTIVITY_FILA_PAYLOAD_MAX 512 // bytes por payload (padrão: 256)
#include <ESP32Connectivity.h>
Não existe método runtime para alterar o tamanho — a fila é um array estático alocado em tempo de compilação, o que evita fragmentação de memória em embarcados.
| Define | Padrão | Descrição |
|---|---|---|
CONNECTIVITY_FILA_SLOTS |
10 |
Número máximo de mensagens na fila |
CONNECTIVITY_FILA_TOPICO_MAX |
64 |
Tamanho máximo do tópico em bytes |
CONNECTIVITY_FILA_PAYLOAD_MAX |
256 |
Tamanho máximo do payload em bytes |
Quando a fila está cheia e uma nova mensagem chega, a mensagem mais antiga é descartada e um aviso é emitido no log ([AVISO]).
Buffer do PubSubClient (tamanho de cada pacote MQTT)
Diferente da fila, o buffer do PubSubClient controla o tamanho máximo de cada mensagem individualmente. O padrão é 256 bytes — se seu payload for maior, aumente antes do begin:
conectividade.configurarBufferMQTT(1024); // mensagens até 1 KB
conectividade.beginSimples(wifi, mqtt, topicos);
Estado
conectividade.wifiConectado(); // bool
conectividade.mqttConectado(); // bool
conectividade.mensagensNaFila(); // uint8_t
Callbacks
conectividade.registrarCallbackWiFiConectado( []() { ... } );
conectividade.registrarCallbackWiFiDesconectado([]() { ... } );
conectividade.registrarCallbackMQTTConectado( []() { ... } );
conectividade.registrarCallbackMQTTDesconectado([]() { ... } );
conectividade.registrarCallbackMensagem(
[](const char* topico, const String& msg) { ... }
);
Debug
// Inicializa o sistema de log (chame antes do begin)
configurarDebug(DEBUG_INFO, 4); // nível INFO, override no GPIO 4
configurarDebug(DEBUG_TUDO, -1); // nível TUDO, sem override
| Nível | Constante | O que exibe |
|---|---|---|
| 0 | DEBUG_NENHUM |
Nada |
| 1 | DEBUG_ERRO |
Falhas críticas |
| 2 | DEBUG_AVISO |
+ Reconexões e timeouts |
| 3 | DEBUG_INFO |
+ Fluxo normal |
| 4 | DEBUG_VERBOSE |
+ Tentativas e estados internos |
| 5 | DEBUG_TUDO |
+ Payloads e códigos de erro brutos |
Exemplos
| Exemplo | Descrição |
|---|---|
00_Template |
Ponto de partida — todos os modos comentados, pronto para parametrizar |
01_WiFiBasico |
Conexão WiFi não-bloqueante com callbacks |
02_MQTTBasico |
WiFi + MQTT com publicação periódica |
03_FilaOffline |
Demonstra enfileiramento e drenagem automática |
Máquinas de estado
WiFi: DESCONECTADO ──begin()──> CONECTANDO ──OK──> CONECTADO
^ | |
└── retry 5s ────────────┘ timeout 15s queda
MQTT: DESCONECTADO ──WiFi OK──> CONECTANDO ──OK──> CONECTADO
^ | |
└── retry 5s ───── falha (máx 5x) broker caiu
Licença
MIT © 2026 professorThiago
ESP32-S3 N16R8 — usando PSRAM para a fila
O modelo N16R8 tem 8 MB de PSRAM externa. Por padrão a fila é alocada na SRAM interna (512 KB). Com PSRAM habilitada, a fila pode ter centenas de slots sem impactar o restante do programa.
platformio.ini para N16R8 com PSRAM
[env:esp32-s3-n16r8]
platform = espressif32
board = esp32-s3-devkitm-1
framework = arduino
board_build.arduino.memory_type = qio_opi
board_upload.flash_size = 16MB
board_build.partitions = default_16MB.csv
build_flags =
-DBOARD_HAS_PSRAM
-DCONNECTIVITY_USAR_PSRAM=1 ; aloca a fila na PSRAM
-DCONNECTIVITY_FILA_SLOTS=200 ; 200 slots × 324 bytes = ~63 KB na PSRAM
Quanto usar?
| Slots | RAM usada (slot padrão 64+256) | Indicado para |
|---|---|---|
| 20 | 6,3 KB — SRAM | Uso geral sem PSRAM |
| 50 | 15,8 KB — SRAM | Logging moderado sem PSRAM |
| 200 | 63 KB — PSRAM | Telemetria, quedas longas |
| 500 | 158 KB — PSRAM | Logging intenso |
| 1000 | 316 KB — PSRAM | Máximo prático |
A PSRAM é ~10× mais lenta que a SRAM interna, mas para uma fila de mensagens (acesso esporádico) isso é imperceptível. A biblioteca detecta automaticamente se a PSRAM está disponível — se
psramFound()retornarfalse, aloca na SRAM sem travar.
Comments