Documentacao
ESP32 e similares
Guia pratico para firmwares Arduino/PlatformIO conectarem ESP32, ESP32-C3, ESP8266 e gateways RF ao IoTsys.
Bibliotecas
lib_deps =
knolleary/PubSubClient@^2.8
bblanchon/ArduinoJson@^7.4.2
sui77/rc-switch@^2.6.4
Fluxo recomendado no firmware
- 1. Wi-FiConectar e reconectar com backoff.
- 2. MQTTAutenticar com credencial do tenant ou dispositivo.
- 3. SubscribeAssinar apenas o topico de comando permitido.
- 4. ExecutarAcionar GPIO, RF, IR, relay ou dimmer.
- 5. ReportarPublicar estado e disponibilidade.
Config basica
#define WIFI_SSID "sua-rede"
#define WIFI_PASS "sua-senha"
#define MQTT_HOST "mqtt.iotsys.com.br"
#define MQTT_PORT 1883
#define MQTT_USERNAME "usuario_mqtt"
#define MQTT_PASSWORD "senha_mqtt"
#define TOPIC_COMMAND "tenants/{tenant_id}/devices/{device_id}/command"
#define TOPIC_STATE "tenants/{tenant_id}/devices/{device_id}/state"
#define TOPIC_AVAILABILITY "tenants/{tenant_id}/devices/{device_id}/availability"
Loop MQTT minimo
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
void publishState(const char *powerState) {
StaticJsonDocument<128> doc;
doc["power_state"] = powerState;
char payload[128];
size_t size = serializeJson(doc, payload);
mqtt.publish(TOPIC_STATE, payload, size);
}
void onMessage(char *topic, byte *payload, unsigned int length) {
StaticJsonDocument<256> doc;
if (deserializeJson(doc, payload, length)) return;
const char *type = doc["type"] | "";
const char *value = doc["value"] | "";
if (strcmp(type, "power") != 0) return;
if (strcmp(value, "ON") == 0) {
// acione relay, dimmer, RF, IR ou GPIO aqui
publishState("ON");
}
if (strcmp(value, "OFF") == 0) {
// desligue o hardware aqui
publishState("OFF");
}
}
Exemplo completo: relay simples
Use este modelo para lampadas, tomadas e cargas acionadas por GPIO. Troque os topicos e credenciais pelos dados exibidos no painel.
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#define RELAY_PIN 23
#define WIFI_SSID "sua-rede"
#define WIFI_PASS "sua-senha"
#define MQTT_HOST "mqtt.iotsys.com.br"
#define MQTT_PORT 1883
#define MQTT_USERNAME "usuario_mqtt"
#define MQTT_PASSWORD "senha_mqtt"
#define TOPIC_COMMAND "tenants/{tenant_id}/devices/{device_id}/command"
#define TOPIC_STATE "tenants/{tenant_id}/devices/{device_id}/state"
#define TOPIC_AVAILABILITY "tenants/{tenant_id}/devices/{device_id}/availability"
WiFiClient wifi;
PubSubClient mqtt(wifi);
void publishState(const char *powerState) {
StaticJsonDocument<128> doc;
doc["power_state"] = powerState;
doc["reported_at"] = nullptr;
char payload[160];
size_t size = serializeJson(doc, payload);
mqtt.publish(TOPIC_STATE, payload, size);
}
void handleCommand(char *topic, byte *payload, unsigned int length) {
StaticJsonDocument<256> doc;
if (deserializeJson(doc, payload, length)) return;
const char *type = doc["type"] | "";
const char *value = doc["value"] | "";
if (strcmp(type, "power") != 0) return;
bool turnOn = strcmp(value, "ON") == 0;
digitalWrite(RELAY_PIN, turnOn ? HIGH : LOW);
publishState(turnOn ? "ON" : "OFF");
}
void connectWifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(300);
}
void connectMqtt() {
while (!mqtt.connected()) {
String clientId = "iotsys-relay-" + String((uint32_t)ESP.getEfuseMac(), HEX);
if (mqtt.connect(clientId.c_str(), MQTT_USERNAME, MQTT_PASSWORD, TOPIC_AVAILABILITY, 1, true, "offline")) {
mqtt.subscribe(TOPIC_COMMAND, 1);
mqtt.publish(TOPIC_AVAILABILITY, "online", true);
publishState(digitalRead(RELAY_PIN) == HIGH ? "ON" : "OFF");
} else {
delay(3000);
}
}
}
void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
connectWifi();
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setCallback(handleCommand);
}
void loop() {
if (WiFi.status() != WL_CONNECTED) connectWifi();
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
}
Exemplo: bridge RF 433 MHz
Para ventiladores, controles RF e botoes virtuais, mapeie comandos do IoTsys para codigos RF. Reporte estado somente depois de enviar o codigo.
#include <RCSwitch.h>
RCSwitch rf = RCSwitch();
const int TX_PIN = 5;
const unsigned long RF_LUZ = 1184891940;
const unsigned long RF_VENTILADOR_VEL6 = 1184892531;
void setupRf() {
rf.enableTransmit(TX_PIN);
rf.setProtocol(1);
rf.setPulseLength(266);
rf.setRepeatTransmit(8);
}
void sendRf(unsigned long code) {
for (int i = 0; i < 8; i++) {
rf.send(code, 32);
delay(10);
}
}
// Dentro do callback MQTT:
// if device == "luz" e value ON/OFF: sendRf(RF_LUZ)
// if device == "ventilador" e value ON: sendRf(RF_VENTILADOR_VEL6)
Reconexao
void connectMqtt() {
while (!mqtt.connected()) {
String clientId = "iotsys-esp32-" + String((uint32_t)ESP.getEfuseMac(), HEX);
if (mqtt.connect(clientId.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) {
mqtt.subscribe(TOPIC_COMMAND, 1);
mqtt.publish(TOPIC_AVAILABILITY, "online", true);
return;
}
delay(3000);
}
}
void loop() {
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
}
Checklist de producao
- Use client ID unico por placa.
- Configure watchdog para recuperar travamentos.
- Reporte estado apenas apos confirmar a acao fisica.
- Evite delay longo dentro do callback MQTT.
- Separe credenciais por tenant, por dispositivo ou por gateway.
- Para gateways RF/IR, publique estado conforme o comando enviado e registre limitacoes fisicas do equipamento.
- Use Last Will MQTT com payload offline para o dashboard refletir quedas de energia ou Wi-Fi.
- Defina intervalos de heartbeat coerentes com o tipo do dispositivo para evitar falso online.