ESP8266 - MQTT - volatile variable

Gast #5984824
Lesenswert?

Hallo,

ich habe ein Problem mit meinem ESP8266 und MQTT.
Ich nutze Arduino IDE und die PubSubClient Bibliothek.

MQTT funktioniert soweit. Ich kann Sensordaten empfangen und Nachrichten 
an den ESP8266 kommen auch an.

Das einzige was nicht funktioniert ist eine variable per MQTT zu setzen.

Ziel: Ich möchte die Meldezeiten der Sensordaten über eine variable 
einstellen.

Umsetzung (vereinfacht, da Prüfung funktionieren):
1
loop() {
2
  checkMQTT();
3
}
4

5
volatile int idleTime = 60000; // jede Minute
6
volatile unsigned int lastRun = millis();
7

8
void checkMQTT() {
9
  if( millis() - lastRun > idleTime) {
10
    // publish sensor data
11
    char[10] msg;
12
    itoa(idleTime, msg, 10); 
13
    client.publish(TOPIC_IDLETIME, msg, true);
14
  }
15
}
16

17
void callback(char* topic, byte* payload, unsigned int length) {
18
  char msg[length+1];
19
  for (int i = 0; i < length; i++) {
20
    Serial.print((char)payload[i]);
21
    msg[i] = (char)payload[i];
22
  }
23
  msg[length] = '\0';
24

25
  if(topic == SET_IDLE) {
26
    idleTime = atoi(msg);
27
    char[10] msg1;
28
    itoa(idleTime, msg1, 10); 
29
    client.publish(TOPIC_IDLETIME, msg1, true);
30
  }
31
}

Wenn ich den Wert 300000 über MQTT sende, dann erhalte ich direkt die 
Antwort 300000 über den publish in der callback routine.

Leider bleibt aber idleTime auf 1 Minute da ich danach auf dem topic 
TOPIC_IDLETIME 60000 erhalte und auch die Sensordaten jede Minute 
kommen.

Habe schon versucht die Variable idleTime static zu setzen aber auch 
kein Erfolg. Ich dachte bisher - und so hat es auch immer funktioniert - 
das volatile die variable nicht weg optimiert.

idleTime wird nirgendwo anders im code verändert.

Woran könnte das liegen, was muss ich ändern?

Besten Dank für eure Hilfe.

Gruß
Jörg
#5985077
Lesenswert?

Eric B. schrieb:
> Jörg schrieb:
>> void callback(char* topic, byte* payload, unsigned int length) {
> ...
>>   if(topic == SET_IDLE) {
>
> Da topic ein char * ist, vermute ich, dass es ein String ist.

Bei MQTT werden alle Nachrichten mit einem "Topic" versendet, der ein 
String ist.

> Strings kann man in C nicht mit einem einfachen == vergleichen.

Man vergleicht damit nicht den Inhalt des Strings, sondern die Adresse. 
Ein char* ist ja ein Zeiger auf einen char. Es steht also eine Adresse 
drin. Bei einem Vergleich wird entspreichend auch diese Adresse 
verglichen, nicht der Inhalt des String.
Interessant wäre noch, wie SET_IDLE definiert ist.
Gast #5985181
Lesenswert?

Hallo,

ok, wie ich geschrieben habe, wurde der code vereinfacht.
Ich habe ja geschrieben, dass die Prüfungen stimmen, da ich den 
Quelltext zu Hause habe, hab ich es vereinfacht.
1
void checkMQTT() {
2
  if( millis() - lastRun > idleTime) {
3
    // publish sensor data
4
    char[10] msg;
5
    itoa(idleTime, msg, 10); 
6
    client.publish(TOPIC_IDLETIME, msg, true);
7

8
    lastRun = millis();
9

10
  }
11
}

lastRun = millis habe ich vergessen zu erwähnen, ist aber drin, sonst 
würde ich ja nie jede Minute einen Wert über MQTT erhalten.

strcmp verwende ich auch in der if-clause. Das funktioniert ja auch. 
Wenn ich einen Wert publishe über topic SET_IDLE, dann melde die 
Anwendung auch über MQTT topic TOPIC_IDLETIME die neue Einstellung, die 
ich gesendet habe.
Aber max. eine Minute später erhalte ich eine Nachricht über die 
Sensordaten und zum Schluss nochmals den Wert TOPIC_IDLETIME.
An dieser Stelle ich der Wert aber wieder auf dem initialen Wert.

Und genau das verstehe ich nicht.

Gruß
Jörg
#5985184
Lesenswert?

Mit Codefragmenten, die grob so ähnlich ist wie das, was du tatsächlich 
machst und den ganzen Prosa-Beschreibungen dazu werden wir hier nicht 
weiter kommen. Zeige echten Code, der nicht so funktioniert, wie 
erwartet, dann hat man auch eine Chance, herauszufinden, warum er nicht 
funktioniert.
Gast #5985249
Lesenswert?

richtig. Vielleicht resettet der ESP auch ständig und startet dann 
wieder mit dem 60s voreingestelltem Wert. Lass mal im setup() eine 
Glocke läuten um irgendwie anzuzeigen das ein Reset ausgeführt wurde. Im 
Broker müsste man das auch sehen wenn der geschwätzig ist.
Gast #5985640
Lesenswert?

Ich kann einfach MQTT.fx nicht bedienen...

Hab auf das Topic gesendet, somit funktioniert meine Abfrageroutine noch 
nicht...
1
void callback(char* topic, byte* payload, unsigned int length) {
2
  char msg[length+1];
3
  for (int i = 0; i < length; i++) {
4
    msg[i] = (char)payload[i];
5
  }
6
  
7
  msg[length] = '\0';
8
  
9
  if(strncmp(topic, MQTT_TOPIC_CISTERN_ACTION_TEMPERATURE, strlen(MQTT_TOPIC_CISTERN_ACTION_TEMPERATURE)) == 0) {
10
    reportTemperature();
11
  } else
12
  if(strncmp(topic, MQTT_TOPIC_CISTERN_ACTION_DELAY, strlen(MQTT_TOPIC_CISTERN_ACTION_DELAY)) == 0) {
13
    idleTime = atoi(msg);
14
    char cstr[16];
15
    itoa(idleTime, cstr, 10);
16
    client.publish(MQTT_TOPIC_CISTERN_SETTINGS_DELAY2, cstr);
17
  } else 
18
  if(strncmp(topic, MQTT_TOPIC_CISTERN_TOPICS, strlen(MQTT_TOPIC_CISTERN_TOPICS)) == 0) {
19
    reportTopics();
20
  } else 
21
  if(strncmp(topic, MQTT_TOPIC_CISTERN_ACTION_DISTANCE_EMPTY, strlen(MQTT_TOPIC_CISTERN_ACTION_DISTANCE_EMPTY)) == 0) {
22
    distanceEmptyInCM = atoi(msg);
23
  } else
24
  if(strncmp(topic, MQTT_TOPIC_CISTERN_ACTION_DISTANCE_FULL, strlen(MQTT_TOPIC_CISTERN_ACTION_DISTANCE_FULL)) == 0) {
25
    distanceFullInCM = atoi(msg);
26
  }
27
}

hier scheint noch der Hund begraben. Mal sehen

Gruß
Jörg
Gast #5985662
Lesenswert?

OH MANN,

# in der subscription vergessen...

Dann funktioniert es auch auf Anhieb.

Fehler 1: Falsche Bedienung MQTT.fx; Publish auf falsches topic.
Fehler 2: # im topic von client.subscribe() vergessen.

Danke für eure Mühen!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren