ElEspanol:
Von der Verwendung ist abzuraten, lies lieber blockierungsfrei ein, jeweils bis zum Zeilenende und mach dann damit, was du brauchst.
Genau so. Lies Zeile für Zeile ein, und suche darin mit strcmp oder strncmp.
Das blockierungsfreie serielle Einlesen ist ein Kapitel für sich, wenn du eine komplette Zeile hast, setzt du ein Flag und aktivierst dann die Auswertungsroutine (EVA-Prinzip) oder machst das in einer if
Das blockierungsfreie serielle Einlesen ist ein Kapitel für sich
Prinzipiell sehr wahr.
Wenn irgendetwas zu tun ist, solange die zu lesende Seite noch nicht fertig angekommen ist, sollte man natürlich nicht darauf warten, dass endlich das kommt auf das man wartet, (oder eventuell etwas fehlt).
Wenn nichts sonst zu tun ist, ist es egal, ob man selbst wartet oder warten lässt.
Zwar ist ein Zeilenende bei eher Nebensache, aber du willst ja nicht einen generellen html oder xml Parser schreiben, sondern auf einer bekannten Seite eine erwartete Struktur und ein paar Zeichen wiedererkennen.
Ob blockierend oder nicht, das eigentliche Problem ist wohl, zu erkennen, ob wohl was schief gegangen ist
nein, das ist Vollschrott. Solche if Gräber macht man nicht. und 3 x ! (!!!) kann Probleme beim kompilieren geben und ist beim Arduino im Prinzip nie nötig.
Mach folgende Schritte, bzw. suche passenden Code und versuche ihn zu verstehen, oder besser, verstehe ihn.
Nicht blockierende Routine, die zeilenweise seriell in einen char array einliest und eine eins (1) zurückgibt, wenn einen Zeilenende erkannt wurde, 0 wenn nicht.
Teste das exzessiv mit dem seriellen Monitor der IDE
Bau einen Timeout ein und gib bei Timeout eine zwei (2) zurück.
Das war Lektion 1
Dann beschäftige dich mit char array und Zeigern darauf, dann damit, wie man innerhalb des Arrays Text sucht und das Ergebnis über einen Zeiger ansprechen kann.
Dann hast du eine gesunde Basis zum weiter machen.
Wenn man nicht alles einlesen will, kann man auch erst mal Zeichen überlesen bis ein bestimmtes Zeichen kommt. Aber danach musst du in ein char Array einlesen. Dabei immer abfragen ob du noch in den Array Grenzen bist! Und wenn das Endzeichen erkannt wurde NULL/0/'\0' in den letzten Index schreiben.
Dann kann man strstr() nach einem Teil-String suchen. Der Rest kommt dann darauf an was man machen will.
if (client.read() == '\n') {
if (client.read() == 'D') {
if (client.read() == 'a') {
if (client.read() == 't') {
if (client.read() == 'e') {
if (client.read() == ':') {
Ist zwar drumherum viel Mist drin, aber wenn "\nDate:" das einzige ist, was er sucht und es nur einmal genau da vorkommt, warum nicht...
Falls der interessierende Text eventuell auf zwei Blöcke aufgeteilt ist, passt das mit dem client.available() nicht sicher...
Problematisch ist das Verhalten auch, wenn -- warum auch immer -- der Suchstring gar nicht vorkommt.
Diese zwei Probleme sind auch beim angedeuteten Änderungsvorschlag (ganze Zeile erstmal in ein char Array) zu beachten.
michael_x:
Falls der interessierende Text eventuell auf zwei Blöcke aufgeteilt ist, passt das mit dem client.available() nicht sicher...
Problematisch ist das Verhalten auch, wenn -- warum auch immer -- der Suchstring gar nicht vorkommt.
Diese zwei Probleme sind auch beim angedeuteten Änderungsvorschlag (ganze Zeile erstmal in ein char Array) zu beachten.
Klar, man sollte schon in etwa wissen, wie die Daten strukturiert sind. Wenn der Suchstring in der Zeile nicht vorkommt, muss eben der Programmierer entscheiden, was passiert. I.a.R. geht man zur nächsten Zeile. Und wenn er da auch nicht ist, zur nächsten, etc.
Das ganze sollte man dann ggf. noch mit einem Timeout versehen, falls notwendig. Und mit einer Fehlerbehandlungsroutine für Pufferüberlauf.
Natürlich ist dies nicht die Universallösung für alles, wie gesagt, es kommt auf die Datenstruktur an. Bei einem Projekt bei mir kommen die Messdaten in Frames von verschiedener Länge ohne CD oder LF, da sieht es dann wieder anders aus.
Aber hier sind es ja html Daten.
Deswegen einen Timeout. Der muss aber je nach Anwendungszweck individuell gemacht werden. Bei html Seiten beispielsweise 2-5 Sek. nach dem ersten erhaltenen Zeichen. Wenn dann das gewünschte nicht gefunden wurde, gehst du in die Fehlerbehandlung.
Paralell kannst du noch nach suchen. Wenn das gefunden wird, gehst du sofort in die Fehlerbehandlung.
Dass du das jetzt noch nicht alles verstehst, ist fast klar. Aber irgendwann fällt es dir wie Schuppen von den Augen und dir wird klar, was gemeint war und vor allem warum.
Je nach Anwendung ist Fehlerbehandlung ein grosser Teil der Programmierarbeit.
Hier ist mal eine grundlegende Funktion um eine Zeile bis zu einem LF einzulesen (ohne Timeout!):
const int STRING_BUFFER_SIZE = 50;
char stringBuffer[STRING_BUFFER_SIZE];
bool readLine(Stream& stream)
{
static int index;
while(stream.available())
{
char c = stream.read();
if(c >= 32 && index < STRING_BUFFER_SIZE - 1)
{
stringBuffer[index++] = c;
}
else if(c == '\n' && index > 0)
{
stringBuffer[index] = '\0';
index = 0;
return true;
}
}
return false;
}
Das geht so egal was die Quelle ist. Serial, SD, Ethernet. Jede Klasse die von Stream abgeleitet ist. Man muss es nur übergeben:
void loop()
{
if (readLine(Serial) == true)
{
}
}
Wenn man nur Serial als Quelle hat reicht das. Hier muss man es erweitern. Wenn man "nichts da", "fertig" und "timeout" unterscheiden will, dann eben statt einem bool einen int zurückgegen
ElEspanol:
Mach folgende Schritte, bzw. suche passenden Code und versuche ihn zu verstehen, oder besser, verstehe ihn.
Nicht blockierende Routine, die zeilenweise seriell in einen char array einliest und eine eins (1) zurückgibt, wenn einen Zeilenende erkannt wurde, 0 wenn nicht.
Teste das exzessiv mit dem seriellen Monitor der IDE
Bau einen Timeout ein und gib bei Timeout eine zwei (2) zurück.
Das war Lektion 1
@stoni99 Also Punkt 1 aus meinem Post 8 wäre nun mit Sereniflys Code schon mal halb erledigt. Jetzt musst du ran