Ir al contenido

← Comandos remotos MQTT en un PLC ESP32 con topic de respuesta

Monitorización textil (tejeduría)ESP32 PLCMQTTControl

Comandos remotos MQTT en un PLC ESP32 con topic de respuesta — ejemplo completo

Opera una flota de PLC ESP32 con comandos remotos MQTT: topics de petición/respuesta, listado de la SD, info del sistema y gestión segura del callback.

Programa completo y ejecutable para el ESP32 PLC (mqtt-remote-commands.ino): incluye cabecera de conexionado, requisitos y notas de integración.

Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales

Vista de solo lectura.

/*
 * COMPLETE EXAMPLE — Remote commands over MQTT with response topic
 *
 * Hardware: ESP32 PLC (Industrial Shields, with WiFi + microSD)
 * Based on: textile monitoring project, modul_MQTT.h
 *
 * Network / topics:
 *   Subscribe:  esp32/{ID}/comands            (incoming commands)
 *   Publish:    esp32/{ID}/comands_response   (PLC response)
 *
 * Commands supported in this example:
 *   info               -> uptime, heap, IP, RSSI
 *   list               -> .json files on the SD card with their size
 *   upload       -> triggers the HTTP upload of the file (separate module)
 *
 * Architecture:
 *   1. The MQTT callback only enqueues the command (flag + buffer): the
 *      heavy work (walking the SD card) is done in the loop, not inside
 *      the callback
 *   2. Every response goes out on the *_response topic with the PLC ID:
 *      a Node-RED console can operate the whole fleet without entering
 *      the plant
 *   3. Unknown command -> explicit error response (diagnostics)
 *
 * Works together with other catalog examples:
 *   - sd-file-upload-http-post.ino (executes the upload command)
 *   - sd-daily-file-datalogging.ino (source of the file listing)
 *   - node-red-multi-plant-concentrator.js (console that sends the commands)
 */

#include 
#include 
#include 

const char *WIFI_SSID = "WIFI_SSID";
const char *WIFI_PASS = "WIFI_PASS";
const char *MQTT_HOST = "BROKER_IP";
const char *MQTT_USER = "MQTT_USER";
const char *MQTT_PASS = "MQTT_PASS";
const int   MQTT_PORT = 1883;
const int   PLC_ID    = 1;

String topicCmd  = "esp32/" + String(PLC_ID) + "/comands";
String topicResp = "esp32/" + String(PLC_ID) + "/comands_response";

WiFiClient net;
PubSubClient mqtt(net);

volatile bool commandAvailable = false;
String pendingCommand = "";

// ------------------------------------------------- Reception (lightweight callback)
void onMqttMessage(char *topic, byte *payload, unsigned int len) {
  String cmd = "";
  for (unsigned int i = 0; i < len; i++) cmd += (char)payload[i];
  cmd.trim();
  pendingCommand = cmd;        // enqueue: the loop processes it outside the callback
  commandAvailable = true;
}

void respond(const String &text) {
  mqtt.publish(topicResp.c_str(), text.c_str());
  Serial.println("RESP> " + text);
}

// ------------------------------------------------- Command execution
void processCommand(const String &cmd) {
  Serial.println("CMD>  " + cmd);

  if (cmd == "info") {
    respond("{\"id\":" + String(PLC_ID) +
            ",\"uptime_s\":" + String(millis() / 1000) +
            ",\"heap\":" + String(ESP.getFreeHeap()) +
            ",\"ip\":\"" + WiFi.localIP().toString() +
            "\",\"rssi\":" + String(WiFi.RSSI()) + "}");

  } else if (cmd == "list") {
    String fileList = "";
    File root = SD.open("/");
    File f = root.openNextFile();
    while (f) {
      if (!f.isDirectory() && String(f.name()).endsWith(".json"))
        fileList += String(f.name()) + " (" + String(f.size()) + " bytes)\n";
      f = root.openNextFile();
    }
    root.close();
    respond(fileList.length() ? fileList : "SD empty");

  } else if (cmd.startsWith("upload ")) {
    String fileName = cmd.substring(7);
    // Delegated to the HTTP upload module (see the corresponding sheet):
    // bool ok = uploadFile("/" + fileName);
    respond("upload of " + fileName + " triggered");

  } else {
    respond("ERROR: unknown command '" + cmd +
            "'. Supported: info | list | upload ");
  }
}

// ------------------------------------------------- Connectivity
void checkMQTT() {
  if (WiFi.status() != WL_CONNECTED || mqtt.connected()) return;
  if (mqtt.connect(("plc" + String(PLC_ID)).c_str(), MQTT_USER, MQTT_PASS)) {
    mqtt.subscribe(topicCmd.c_str());      // re-subscribe after every reconnection
    Serial.println("MQTT connected, subscribed to " + topicCmd);
  }
}

void setup() {
  Serial.begin(115200);
  SD.begin();

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  uint32_t t0 = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - t0 < 15000) delay(500);

  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setCallback(onMqttMessage);
  checkMQTT();
}

void loop() {
  checkMQTT();
  mqtt.loop();

  if (commandAvailable) {      // process outside the MQTT callback
    commandAvailable = false;
    processCommand(pendingCommand);
  }

  delay(20);
}
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales