Text mit Textfinder einlesen

Wie kann ich mit dem Script Textfinder auch Text einlesen? Hier ein kurzer Auszug:

finder.find("<wind_dir");
    int R = finder.getValue();
    lcd.setCursor(11,0);
    lcd.print("R:");
    lcd.print(R);
    delay(3000);

Mit Zahlen funktioniert das zwar, nur nicht mit Text. Wind_dir sollte z.B. SSW, also die Wind Richtung ausgeben.

Micky

-Micky:
Mit Zahlen funktioniert das zwar, nur nicht mit Text.

Zum Suchen von Text müßtest Du ja wohl auch finder.getString() aufrufen und einen zusätzlichen post_string angeben, mit Text, der hinter dem gesuchten Wert steht. Siehe Library-Dokumentation:
http://playground.arduino.cc/Code/TextFinder
(Falls das der Textfinder ist, von dem Du hier gepostet hast.)

Den Textfinder meine ich. Kannste mal bitte ein Beispiel schreiben? Ich versteh das nicht.

Micky

-Micky:
Den Textfinder meine ich. Kannste mal bitte ein Beispiel schreiben? Ich versteh das nicht.

Hast Du meinen Beitrag gelesen? Ich schrieb:

Zum Suchen von Text müßtest Du ja wohl auch finder.getString() aufrufen und einen zusätzlichen post_string angeben, mit Text, der hinter dem gesuchten Wert steht.

Deinen "post_string" möchtest Du nicht angeben?
Ist wohl geheim, oder was?

OK, den pre_string hast Du ja mit "<wind_dir" angegeben. Wenn der post_string so geheim ist, dass Du ihn nicht verraten kannst, dann rate ich jetzt mal, dass das vielleicht einfach ein Semikolon ";" sein könnte und die Windrichtung sei niemals länger als 5 Zeichen.

Ich kenne Deine Library zwar nicht, aber dann sollte das für einen eintreffenden Text mit dem Inhalt "abcdefg<wind_dirSSW;hijklmnop" ungefähr so funktionieren:

  char buf[6];  // Puffer deklarieren
  memset(buf,0,sizeof(buf)); // Puffer löschen
  int count=finder.getString("<wind_dir", ";", buf, sizeof(buf));
  if (count>0) Serial.println(buf); // das ist dann der Text zwischen "<wind_dir" und ";".

Danke! Hat funktioniert.

Was bitte ist ein post_string?!

Micky

-Micky:
Was bitte ist ein post_string?!

Das ist erstmal nur der Name einer Variablen in der Funktionsdeklaration.

Allerdings ein "sprechender" Variablenname.
Das lateinische Wort "post" bedeutet "nach".

D.h. wenn man einigermaßen raten kann und Latein in der Schule hatte oder englische pm-Zeitangaben (p.m.= post meridiem, nach dem Mittag) etwas sagen, dann ist "post_String" ein String "nach" dem gesuchten Text.

Ah, danke.

Hatte nie Latein. Und mit AM und PM stehe ich auf Kriegsfuß.

Micky

mit AM und PM stehe ich auf Kriegsfuß

Das sollte dir keine Minderwertigkeitskomplexe verursachen.

Wer den Wechsel AM/PM zwischen 11 und 12 legt, die erste Stunde nach Mitternacht 12 nennt, und die nächste 1, dem ist wirklich nicht zu helfen.
Das Römische Reich ist nicht untergegangen, weil Obelix in den Zaubertrank gefallen ist, sondern weil die Lateiner nicht rechnen können. Ohne Null und wenn die Zahlen nur bis tausend gehen, kommt man nicht weit.

Und wo ich schon mal am Motzen bin:
Du kämst wohl auch weiter ohne StringFinder-Schnickschnack.
Bis man den verstanden hat, hat man sich das Benötigte selbst gebaut ( mit jurs' Hilfe allemal )
:wink:

michael_x:
Das Römische Reich ist nicht untergegangen, weil Obelix in den Zaubertrank gefallen ist, sondern weil die Lateiner nicht rechnen können. Ohne Null und wenn die Zahlen nur bis tausend gehen, kommt man nicht weit.

Nur so zur Information die Römer konnten über 100o rechenen. Dazu gabs zB einen Strich über den Zeichen.

Aber ok das war nicht so flexibel wie binäre Zahlen die nur die Werte 1 oder 0 annehmen können. :wink: :wink: :wink:
Grüße Uwe

Und wie bekommt man die "" rausgefiltert?

int count1=finder.getString("percent=", "/>", buf, sizeof(buf));
    if (count1>0)

Ausgabe auf dem LCD Display ist dann: "92.7"

Micky

Das könnte gehen:

int count1=finder.getString("percent=\"", "\"/>", buf, sizeof(buf));

Du musst halt noch die Anführungszeichen hinzufügen und jeweils mit \ escapen

Sowas kann man eigentlich auch relativ einfach mit sscanf() machen:
http://www.cplusplus.com/reference/cstdio/sscanf/
http://www.cplusplus.com/reference/cstdio/scanf/

Auf dem Arduino hat man da das Problem, dass das für Float nicht implementiert ist. Es gibt zwar eine upgedatete Lib dafür, aber man kann es auch als String auslesen:

char str[] = "<cloudiness id=\"NN\" percent=\"92.7\"/>";
char buf[6];
sscanf(str, "%*[^0-9]%[.0-9]", buf);

Man liest alle Zeichen ein die nicht Zahlen sind (das ^ ist eine Negation). Und dann alle Zeichen die ein Punkt oder eine Zahl ist.
Der Stern bedeutet dabei, dass die Sequenz nicht in eine Variable geschrieben wird, sondern überlesen wird.

Falls bei "id=" mal eine Zahl drin stehen könnte, funktioniert dieser Format String:
"%*s%s%[^0-9]%[.0-9]"

Die Version eins funktioniert sehr gut. Danke! Version zwei gibt keinen Wert zurück. Habe mehrere Varianten ausprobiert, klappt aber nicht.

Micky

Mhh, muss sagen dass es ich nur in Visual C++ getestet habe und nicht auf dem Arduino, aber das sollte eigentlich genauso gehen.

Naja. Du hast ja den TextFinder. Da muss man keine zweite Lib einfügen. Das vergrößert auch nur das Programm :slight_smile:

Ah ok. Geht einfach nicht.

Da hast Du recht. Mit dem Textfinder geht das auch. Obwohl ich die andere Version schöner finde.

Micky

Habe eine stdinout.cpp gefunden. Funktioniert soweit so gut, nur wird der gesendete Wert nicht ausgegeben, sondern nur der voreingestellte.

Micky

stdio.h wird standardmäßig im Hintergrund inkludiert. Da muss man eigentlich sonst nichts machen, oder der Compiler würde das gar nicht schlucken:
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

Dass ich da den String fest vorgegeben habe, war auch nur zum Testen. Das musst statt der Variable "str" deinen String übergeben. Weiß nicht wie du den genau vorliegen hast. Das schluckt nur einen char*, bzw. ein char Array.

TextFinder arbeitet da mit einem Stream als Argument, z.B. ein Ethernet Client oder Serial. Das ist für deine Anwendung vielleicht generell praktischer. :slight_smile:

Ok, ich bleibe beim Textfinder. Das andere ist mir zu kompliziert. Aber hier mal mein Script:

#include <SPI.h>
#include <Ethernet.h>

#include <TextFinder.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// Änderung 1 
char serverName[] = "api.met.no";

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
char buf[8];  // Puffer deklarieren

TextFinder  finder( client );  

void setup() {
 
  lcd.init(); // initialize the lcd
  lcd.backlight();
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    while(true);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:

  if (client.connect(serverName, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    // Änderung 2
    client.println("GET /weatherapi/locationforecastlts/1.1/?lat=60.10;lon=9.58");
    client.print("Host: ");client.println(serverName); 
    client.println();
  } 
  else {
    // kf you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop()
{
  // if there are incoming bytes available 
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
memset(buf,0,sizeof(buf)); // Puffer löschen
  } 
  
    finder.find("<temperature");
    int temperature = finder.getValue();
    //lcd.clear();
    lcd.setCursor(0,0);
    //lcd.print("T=");
    lcd.print(temperature);
    lcd.setCursor(3,0);
    lcd.print((char)223);
    lcd.print("C "); 
    delay(3000);
    
    int count=finder.getString("name=\"", "\"/>", buf, sizeof(buf));//Windrichtung
    if (count>0) 
    lcd.setCursor(12,0);
    lcd.print(buf); // das ist dann der Text zwischen "<wind_dir" und ";".  
       
    finder.find("<humidity");
    int Lf = finder.getValue();
    lcd.setCursor(6,0);
    lcd.print("F");
    lcd.setCursor(8,0);
   
    lcd.print(Lf);
    lcd.setCursor(10,0);
    lcd.print("%");
    delay(3000);
      
    int count1=finder.getString("percent=\"", "\"/>", buf, sizeof(buf));//Deckung Wolken
    if (count1>0) 
    lcd.setCursor(9,1);
    lcd.print("B");
    lcd.setCursor(11,1);
    lcd.print(buf); // das ist dann der Text zwischen "<wind_dir" und ";".  
    delay(3000);
    
    finder.find("<pressure");
    int pressure = finder.getValue();
    lcd.setCursor(0,1);
    //lcd.print("D:");
    lcd.print(pressure);
    lcd.setCursor(5,1);
    lcd.print("hPa");
    delay(3000);
   
   // if the server's disconnected, stop the client:
   //if (!client.connected()) {
   
    client.stop();
    client.flush();  
    delay(600000); // 10 Minuten warten
    
    }

Ich sehe hier keinen String. Fehlt wohl. Nur wie der heißen muß weiß ich nicht. Ist mir zu kompliziert.

Micky

Der String ist irgendwie in client verpackt, was das Objekt ist welches du an TextFinder übergibt. Das kann man auslesen (mit read(), da das Ding an Serial angelehnt ist), aber am Besten du lässt es so :slight_smile: Macht nur unnötig Arbeit das zu ändern.

Ich laß das jetzt so.

Wie kann ich gezielt bei diesen Wettervorhersagen nur immer diejenige Abfragen die ganz oben steht?

http://api.met.no/weatherapi/locationforecastlts/1.1/?lat=60.10;lon=9.58

So wie ich das eben habe geht der die alle der Reihe nach durch. Oder, wenn ich was ändere, wird die oberste einmal eingelesen und dann nicht wieder.

Micky

Habe es hinbekommen. Nicht sehr elegant aber es funktioniert.

Micky