pubsubclient - LastWill kommt nicht an

Hallo zusammen,
ich experimentiere derzeit mit Arduinos und MQTT. Dafür nutze ich die Library "pubsubclient".

Senden und Empfangen funktioniert alles gut. Nur der Letzte Wille kommt beim Kappen der Stromversorgung des Arduinos nicht.

Der Code kompiliert ohne Fehlermeldungen durch und der Client verbindet sich auch zum Broker (Mosquitto 0.15 => MQTT Version in pubsubclient auf 3_1 geändert).

Habt ihr eine Idee, was da falsch laufen könnte?

ich hänge mal die MQTT-Verbindungs-Funktion an:

void MQTT_Connect(){

  char *will = const_cast<char*>(willtopic.c_str());       //String in Chararray wandeln
  
  if (client.connect((char*) clientName.c_str()),will,0,true, "OFFLINE") {

    Serial.println("Verbunden mit MQTT broker");

    if (client.publish(will, "Online", true)) {
      Serial.println("Publish ok");
    }
    else {
      Serial.println("Publish fehlgeschlagen");
    }
  }
  else {
    Serial.println("MQTT Verbindung fehlgeschlagen");
    Serial.println("Versuche es nochmal....");
    abort();
  } 
}

Ich würde mich sehr über Denkanstöße freuen.

Ein schönes Wochenende!
Grüße,
Ingo

Heyho...
Habe mich auch mal daran versucht, bei mir funktioniert es. Allerdings weiß ich schon mal nicht, was bei Dir clientName und willtopic für ein Format haben. Eventuell kann bei Dir da etwas in der Formatierung falsch laufen....
Kannst ja mal zum Beispiel will ausgeben lassen, bevor Du es übergibst.
Zudem kannst Du zur genaueren Kontrolle mal den MQTT-Spy nebenher laufen lassen, da siehst Du genau, was für Nachrichten im System umherschwirren (wenn die Verbindung steht, musst Du auf # subscriben, dann hast alles dabei)
Mir ist zudem aufgefallen, dass es relativ lange braucht, bis die lastWill-Nachricht abgeschickt wird, ca 20 Sekunden. Warst vielleicht etwas zu ungeduldig? :smiley:

Hey,
danke für die Antwort.
Das war mal wieder ein klassischer Fall von "Tomaten auf den Augen"...

Kaum macht man es richtig, funktioniert es auch.

clientName und willtopic sind Strings, da ich sie vorher zusammen setze. Das hat aber tatsächlich nichts mit der Lösung zu tun.

Die liegt in der connect-Zeile.

if (client.connect((char*) clientName.c_str()),will,0,true, "OFFLINE") {
...
}

die Klammer hinter clientName.c_str() gehört nicht an diese Stelle, sondern hinter die Klammer hinter "OFFLINE".

if (client.connect((char*) clientName.c_str(),will,0,true, "OFFLINE")) {
...
}

Warum auch immer er das so durch kompiliert hat???

So hat die connect-Funktion immer nur den clientName mitbekommen, aber nicht das was danach kam.

Vielen Dank für die Denkanstöße und noch einen schönen Sonntag!

Grüße,
Ingo

P.S.: Bitte als gelöst markieren.

Die liegt in der connect-Zeile.

-->Ok, leicht zu übersehen xD

Warum auch immer er das so durch kompiliert hat???

-->if() benötigt letzten Endes nur einen Ausdruck, der zu 0 oder nicht 0 führt. Bei den Parametern ist das durchaus gegeben, nur weiß ich gar nicht, wie er mit den Kommas umgeht... Werd ich mir bei Gelegenheit mal näher ansehen, vielleicht ist es gar nicht so sinnlos, wie es auf den ersten Blick scheint^^ (oder ein Anderer weiß da bereits Bescheid)

Übrigens noch ein Denkanstoß: mit Strings sollte man eher sparsam bzw. gar nicht umgehen, wieso nutzt nicht char-Arrays? Wenn es denn Strings sein müssen, dann schau Dir mal den pubsubclient von Imroy an, der arbeitet mit Strings und ist dahingehend komfortabler. Nachteil: beide Libs haben den gleichen Namen, man müsste die eine Lib durch die andere ersetzen, wenn man mit der arbeiten möchte.

Hey,

ich weiss, dass das mit den Strings eher suboptimal ist.
Dennoch habe ich keine (einfache) Möglichkeit gefunden char-Arrays dynamisch zu erweitern. (So lange mach ich das auch noch nicht :wink: )

Es ist halt ein MQTT-Client, wo ich am Anfang des Sketches Namen und Raum und sowas angebe und was dann halt im weiteren Programmablauf zusammen gesetzt wird.

z.B. (Auszug):

String settopic = "";

char* Name = "LED-Dimmer";
char* Raum = "Testraum";

void setup(){
    settopic = "zuHause/";
    settopic += Raum;
    settopic += "/";
    settopic += Name;
    settopic += "/";
}

Hättest du da einen geschickteren Vorschlag?

Danke und Grüße,
Ingo

Dennoch habe ich keine (einfache) Möglichkeit gefunden char-Arrays dynamisch zu erweitern.

-->Tjo, bei den char-Arrays muss man ziemlich tüfteln.
Habe mal auf die Schnelle und im Halbsuff aus Spaß an der Freude was zusammengefrickelt, was so funktioniert. In eine Funktion ausgelagert, wo Du Zeiger auf die Arrays (Array1, Array2) übergibst, könnte das was werden. Mögliches Problem: wo wird das Ziel- char-Array erstellt? Oder aber Du verwendest einen Buffer mit festgelegter Größe.

  char charA[] = "ArrayA";
  char charB[] = "ArrayB";
  char targetBuff[sizeof(charA)+sizeof(charB)-1];
  for(int i=0; i<sizeof(charA)-1; i++){
    targetBuff[i]=charA[i];
  }
  targetBuff[sizeof(charA)-1]='\0';
  for(int i=sizeof(charA)-1; i<(sizeof(charA)-1+sizeof(charB)-1); i++){
    targetBuff[i]=charB[(i-sizeof(charA))+1];
  }
  targetBuff[sizeof(charA)-1+sizeof(charB)-1]='\0';
}

Das jedenfalls nur mal so als Anstoß, vielleicht kannst da ja mehr draus machen. In einem älteren Projekt habe ich es ähnlich gemacht wie Du: String erstellt, char-Array erstellt, String in char-Array gepackt und das Array dann an den Pubsubclienten übergeben.

Oder aber Du stellst auf den von mir erwähnten abgeänderten Pubsubclienten um, welcher sowieso mit Strings arbeitet.... das ist übersichtlicher und einfacher.

char *will = const_cast<char*>(willtopic.c_str());

Wieso willst du das const weg-casten? Das sollte hier eigentlich keinen Fehler verursachen da nur Lesend darauf zugegriffen wird

Wenn es String Objekte sein sollen dann sollte man reserve() verwenden um vorher die Größe festzulegen.

Hey,

Serenifly:
Wieso willst du das const weg-casten?

Die Frage ist sehr leicht zu beantworten: Unwissenheit.

Wie gesagt - so lange mache ich das noch nicht. Ich übe noch und probiere vieles was ich im Netz finde einfach mal aus.

Dieser cast war eines dieser Fundstücke :wink:

Grüße,
Ingo

Der const-cast ist eine der Dinge die du erst mal vergessen solltest :slight_smile: Const ist aus da aus gutem Grund da (da man nicht auf das interne Array des Objekts schreiben soll) und es gibt sehr wenige Situationen wo man das braucht. Wenn man das verwendet sollte man genau wissen was man tut.