IoTsys
Menu

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. 1. Wi-FiConectar e reconectar com backoff.
  2. 2. MQTTAutenticar com credencial do tenant ou dispositivo.
  3. 3. SubscribeAssinar apenas o topico de comando permitido.
  4. 4. ExecutarAcionar GPIO, RF, IR, relay ou dimmer.
  5. 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.