Hallo liebes Forum
Stehe wieder mal an: Ich schicke vom Arduino einen POST zum meinem Webserver. Dieser verarbeitet ein Skript mit den Werten und schickt dem Arduino den Status zurück.
Das funktioniert recht gut. Doch leider gibt es zwischendurch den Fall, dass Arduino die Rückmeldung nicht erhält, obwohl das Skript erfolgreich durchläuft. Mit einem delay() verbessert sich die Situation.
Am liebsten hätte ich aber, dass Arduino auf die Antwort wartet (mit Timeout), so dass im Normalfall keine künstliche Verzögerung eingebaut werden muss.
Hier die Funktion:
boolean postStatus(String Nachricht) {
if (client.connect(WebServerIP,SMARTHOMESERVER_PORT)) {
//POST an Webserver
client.println(F("POST /input_arduino.php HTTP/1.1"));
client.print(F("Host: "));
client.println("192.168.1.170");
client.println(F("Content-Type: application/x-www-form-urlencoded"));
client.println(F("Connection: close"));
client.println(F("User-Agent: Arduino/1.0"));
client.print(F("Content-Length: "));
client.println(Nachricht.length());
client.println();
client.print(Nachricht);
client.println();
//Antwort vom Webserver
delay(100);
while (client.available()) {
String line = client.readStringUntil('\n');
if (line.indexOf("Status=OK") >= 0) {
return true;
}
}
client.stop();
}else{
Serial.println(F("Keine Verbindung zum Webserver!"));
}
}
Edit: Wenn Du die OK-Meldung erkennst, brichst Du ab, erreichst also nicht das client.stop().
Merke Dir den Zustand in einer Variablen und gib ihn am Ende zurück, wenn Du alles gelesen hast.
Hi Tommy
Die Antwort ist nicht angekommen, das Skript auf dem Webserver aber wurde erfolgreich ausgeführt.
Umso kleiner ich den delay() wähle umso öfter tritt dieser Fall auf.
Für den client.stop() habe ich den Code angepasst:
boolean postStatus(String Nachricht) {
boolean booReturn;
if (client.connect(WebServerIP,SMARTHOMESERVER_PORT)) {
//POST an Webserver
client.println(F("POST /input_arduino.php HTTP/1.1"));
client.print(F("Host: "));
client.println("192.168.1.170");
client.println(F("Content-Type: application/x-www-form-urlencoded"));
client.println(F("Connection: close"));
client.println(F("User-Agent: Arduino/1.0"));
client.print(F("Content-Length: "));
client.println(Nachricht.length());
client.println();
client.print(Nachricht);
client.println();
//Antwort vom Webserver
delay(1);
while (client.available()) {
String line = client.readStringUntil('\n');
if (line.indexOf("Status=OK") >= 0) {
booReturn = true;
}
}
client.stop();
}else{
Serial.println(F("Keine Verbindung zum Webserver!"));
}
return booReturn;
}
Dann musst Du aber auch noch den anderen Zweig bearbeiten:
}else{
Serial.println(F("Keine Verbindung zum Webserver!"));
booReturn = false;
}
[code]
wie meinst Du das: Die Antwort kommt nicht an?
Wie sieht denn Dein Script auf dem Server aus?
Gruß Tommy
Wenn ich mir die Antwort des Webservers mit Serial.print(line) ausgebe, kommt manchmal nichts. Wenn ich den delay() erhöhe auf zB 3 kommt die Antwort vom Webserver zu ca 90% an, in ca 10% kommt einfach nichts.
Das Script auf dem Server macht Einträge in die Datenbank und wenn diese erfolgreich waren kommt ein Status=OK.
Die Datenbank Einträge werden interessanterweise in jedem Fall geschrieben. Es scheint als würde die Antwort unterwegs zum Arduino verloren gehen.
boolean postStatus(String Nachricht) {
boolean booReturn;
if (client.connect(WebServerIP,SMARTHOMESERVER_PORT)) {
//POST an Webserver
client.println(F("POST /input_arduino.php HTTP/1.1"));
client.print(F("Host: "));
client.println("192.168.1.170");
client.println(F("Content-Type: application/x-www-form-urlencoded"));
client.println(F("Connection: close"));
client.println(F("User-Agent: Arduino/1.0"));
client.print(F("Content-Length: "));
client.println(Nachricht.length());
client.println();
client.print(Nachricht);
client.println();
//Antwort vom Webserver
delay(1);
while (client.available()) {
String line = client.readStringUntil('\n');
if (line.indexOf("Status=OK") >= 0) {
booReturn = true;
}
Serial.println();
Serial.print(line);
}
client.stop();
}else{
Serial.println(F("Keine Verbindung zum Webserver!"));
booReturn = false;
}
return booReturn;
}
du wartest nicht wirklich. Du verzögerst nur das einlesen von der seriellen mit dem delay. Du fragst ja sofort nach senden den Empfang ab und wenn da nichts ist schlägt es fehl. Du musst nachdem senden die serielle permanent abfragen und darfst hier keine Fehlermeldung erstellen. Denn du weiß nicht wann die Antwort kommt.
Du kannst dir nachdem senden eine Zeit merken, fragst immer die serielle ab und lässt parallel noch eine Timeout laufen. Entweder kommt innerhalb des Timeouts eine Antwort oder das Timeout schlägt zu.
So mache ich das jedenfalls zusammen mit einem Zustandsautomaten.
Sendezustand, wechselt nach dem senden in den Empfangszustand womit auch das Timeout aktiv wird.
Danach wechselt es wieder in den Sendezustand. Oder vorher wird das Timeout behandelt.
Edit:
auch solltest du die Einlesefunktion trennen. Erst wenn die reine serielle Einlesefunktion ein okay zurück gibt, kann die Antwort ausgewertet werden.
while finde ich nicht gut, dass wird oder kann auch blockieren. if ... availble ist besser. Deine loop muss permanent durchlaufen können. Da das aber Ethernet ist, kenne ich mich da nicht so aus. Aber das Prinzip sollte wie mit der seriellen ablaufen. Du musst dir nur vorstellen das der Code ständig durchlaufen wird, mit jeden empfangenen Byte wird kurz das if ... availble aktiv, wenn nichts da ist wird ignoriert. Wenn aber diese Einlesefunktion bemerkt das Datenprotkoll wurde komplett empfangen, gibts ein okay/true zurück und die nächste Funktion zur Auswertung der empfangenen Daten wird aktiv.
Das ist wie ein Dauerlauf im Kreis. Du fährst deine Runde am Bäcker vorbei immer und immer wieder. Wenn du mitbekommst der hat jetzt geöffnet, erst dann springste kurz raus, kaufst deine Semmeln und drehst weiter deine Runden. Dabei öffnest du den Beutel, jetzt stellste fest, alles vollständig, verlässt wieder kurz die Runde, biegst kurz nach Hause ab und lieferst den kompletten Einkauf. Danach drehste wieder deine Runden. Bis irgendein nächstes Ereignis eintritt. Beim Einkauf haste die Stoppuhr nebenbei gestartet und als du bemerkt hast der Beutel ist komplett haste diese wieder gestoppt.