i have the following setup:
First:
ESP32 (D1 Mini NodeMCU WiFi Modul) with an Potentiometer. If i turn the Poti, a variable changes between 0-100 and gets published via MQTT to a Broker on the Topic "remoteServo/PotiValue". That is running on my Homeassistant server.It is working fine, if i turn the Poti, the value changes.
Here a picture of my Homeassistant Server, if i listen to this topic:
Second:
A second ESP32 with which i want to receive the value published on the Topic "remoteServo/PotiValue". I tried it witht he following Code, but i do not get the value that i publish with the first ESP. I looked at about a dozen diffenent examples online, but it seems like there is a thinking error. Can someone tell me what i did wrong?
#include "OTA.h"
#include <credentials.h>
#include <WiFi.h>
#include <PubSubClient.h>
String clientId = "ESP32-Nr1";
#define inTopic "remoteServo/PotiValue"
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
String message = message + (char) payload[i]; // convert *byte to string
Serial.print(message);
}
Serial.println();
}
WiFiClient espClient;
PubSubClient client(myMQTTSERVER, 1883, callback, espClient);
long lastMsg;
void setup() {
delay(100);
Serial.begin(115200);
while (!Serial);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(mySSID);
WiFi.begin(mySSID, myPASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
client.setServer(myMQTTSERVER, 1883);
client.subscribe(inTopic);
client.setCallback(callback);
}
void loop() {
ArduinoOTA.handle();
if (!client.connected()) {
reconnect();
}
long now = millis();
if (now - lastMsg > 5000) {
Serial.println("Send new Data");
lastMsg = now;
delay(1000);
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
Serial.println("connected");
client.subscribe(inTopic);
Serial.println("Subscribed to topic: inTopic");
} else {
Serial.print("failed, rc=");
Serial.println(client.state());
delay(5000);
}
}
}
Here is some code that I use to run client.loop(). If client.loop() is not run then receiving a publication will not happen.
/*
Important to not set vTaskDelay/vTaskDelayUntil to less then 10. Errors begin to develop with the MQTT and network connection.
makes the initial wifi/mqtt connection and works to keeps those connections open.
*/
void MQTTkeepalive( void *pvParameters )
{
sema_MQTT_KeepAlive = xSemaphoreCreateBinary();
xSemaphoreGive( sema_MQTT_KeepAlive ); // found keep alive can mess with a publish, stop keep alive during publish
MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds makes for a very reliable connection, must be set before the 1st connection is made.
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 250; //delay for ms
for (;;)
{
//check for a is-connected and if the WiFi 'thinks' its connected, found checking on both is more realible than just a single check
if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
{
xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); // whiles MQTTlient.loop() is running no other mqtt operations should be in process
MQTTclient.loop();
xSemaphoreGive( sema_MQTT_KeepAlive );
}
else {
log_i( "MQTT keep alive found MQTT status % s WiFi status % s", String(wifiClient.connected()), String(WiFi.status()) );
if ( !(wifiClient.connected()) || !(WiFi.status() == WL_CONNECTED) )
{
connectToWiFi();
}
connectToMQTT();
}
//log_i( " high watermark % d", uxTaskGetStackHighWaterMark( NULL ) );
xLastWakeTime = xTaskGetTickCount();
vTaskDelayUntil( &xLastWakeTime, xFrequency );
}
vTaskDelete ( NULL );
}
So it seems like, it never reaches the "void callback" function. If i subsribe via client.subscribe(inTopic); , shouldnt this function be called if i a new value is published? Or do i have to call the callback function manually? Could it have something to do with the "Retain:false" flag of the published value?
Second Question:
The clientId for the ESP32 who publishes the Data is:
String clientId = "ESP32-Nr4";
So publish ESP32 has ESP32-Nr4, the subscribe ESP32 has ESP32-Nr1
That is only the case if i use the client.loop();, which i did not do in the beginnng.
There is also no schematic. The 2nd Esp32 that should receive the data of the 1st ESP32 is only plugged in into the PC. Changing the PC port or switching to an external supply does not help. Changing the Esp32 does not help.