PHP echo mittels Arduino Yun auslesen

Guten Tag,

ich habe folgendes Problem:
und zwar habe ich eine PHP Datei die mittels eines Echos einen String ausgibt.
Diesen String fange ich mittlerweile mit der Methode .get(url) ab. Problem hierbei ist ich kann diesen “String” nur char weise abrufen und an eine Variable vom Typ String im Arduino Yun anhängen, wie man im folgenden Skript auch sieht.
Meine Frage nun kennt jemand eine bessere Möglichkeit bzw. eine Möglichkeit die Zeit sparender ist da mein Projekt ziemlich Zeitabhängig ist.
Vielen Dank schon mal an alle die mithelfen.

   //Objekte und Variablen
  HttpClient httpclient;
  String str_returnVal="";
  String uebergabe;
  char c;
     // Get Aufruf mit Parameter = 2 um die alle Values der Assets zu erhalten
  httpclient.get("http://192.168.1.14/xampp/scripts/Arduino_PHP.php?parameter=2");
  // Rückgabewert (einzelne chars)der PHP datei in eine Variable schreiben



  while (httpclient.available()) {
    c = httpclient.read();
    if (c != '\n' && c != '\r') {
        str_returnVal += c;
    }
  }



  // Rückgabewert  splitten und in ein Array schreiben
  int y=0;
  for(int i=0;y < MaxAssets;i++){
    if(str_returnVal[i] == ';'){  
         if(uebergabe != str_ar_saveVals[y]){
            str_ar_saveVals[y] = uebergabe;
            uebergabe="";
         }
         y++;
         uebergabe="";
    }else{
         uebergabe += str_returnVal[i];
    }
  }

Die Ausgabe der PHP Datei könnte Beispielsweise so aussehen:

2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;2000;;

Diese Werte werden dann halt gesplittet und nachher einzelnt verwendet.
Jedoch geht es mir hauptsächlich um die While schleife in denen der Char geholt wird. Am schönsten wäre es natürlich wenn der get Befehl direkt in eine String Variable gespeichert würde.

Auf die String Klasse verzichten und Null-terminierte char Arrays verwenden. Wie in C üblich. und strtok() für das Splitten und atoi() für die Wandlung in Integer. Das ist wesentlich ressourcenschonender und viel schneller.

Hier mal Prinzip Code mit Eingabe über Serial:

const int INPUT_BUFFER_SIZE = 41;
char inputBuffer[INPUT_BUFFER_SIZE];

const int MAX_NUMBERS = 4;
int numbers[MAX_NUMBERS];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (readSerial() == true)
    parseSerial();
}

bool readSerial()
{
  static byte index;

  while (Serial.available())
  {
    char c = Serial.read();

    if (c >= 32 && index < INPUT_BUFFER_SIZE - 1)
    {
      inputBuffer[index++] = c;
    }
    else if (c == '\n' || c == '\r')
    {
      inputBuffer[index] = '\0';
      index = 0;
      return true;
    }
  }
  return false;
}

void parseSerial()
{
  char* token = strtok(inputBuffer, ";");
  int index = 0;

  while (token != NULL && index < MAX_NUMBERS)
  {
    numbers[index++] = atoi(token);
    token = strtok(NULL, ";");
  }

  for (int i = 0; i < index; i++)
    Serial.println(numbers[i]);
  Serial.println(F("---------"));
}

Und wenn es schon unbedingt String Objekte sein müssen, dann verwende sie wenigstens richtig! Das heißt erst mal Speicher mit reserve() reservieren:
http://arduino.cc/en/Reference/StringReserve

Das macht wohl kaum jemand, aber damit verhinderst du das erst jedesmal der Speicherbereich erweitert werden muss, wenn ein Zeichen angehängt wird. Neben der fehlenden Funktionalität ist der ineffektive Umgang mit dynamischem Speicher ein Hauptgrund weshalb die String Klasse so schlecht ist.

Wenn man nur positive Integer hat kann man das aber auch einfach machen ohne erst mal den ganzen String abzuspeichern. In dem man immer die aktuelle Ziffer auf den bisherigen Wert * 10 addiert. Werde da später vielleicht mal Code posten.

Wenn man in ein int Array einliest, kann man das auch erst mal so optimieren, dass man zwar atoi() verwendet, aber nicht den ganzen String komplett einliest sondern immer nur die Zeichen einer Zahl.

Das hängt aber von der Anwendung ab und was man mit den Zahlen macht. Manchmal braucht man auch den kompletten String.

const int INPUT_BUFFER_SIZE = 10;
char inputBuffer[INPUT_BUFFER_SIZE];

const int MAX_NUMBERS = 4;
int numbers[MAX_NUMBERS];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int num = readSerial();

  if (num > 0)
  {
    Serial.print("numbers: "); Serial.println(num);

    for (int i = 0; i < num; i++)
      Serial.println(numbers[i]);
    Serial.println(F("---------"));
  }
}

int readSerial()
{
  static byte charIndex;
  static byte numberIndex;

  while (Serial.available())
  {
    char c = Serial.read();

    if (c >= '-' && c <= '9' && charIndex < INPUT_BUFFER_SIZE - 1)
    {
      inputBuffer[charIndex++] = c;
    }
    if (c == ';' || c == '\n' || c == '\r')
    {
      if (numberIndex < MAX_NUMBERS)
      {
        inputBuffer[charIndex] = '\0';
        charIndex = 0;
        numbers[numberIndex++] = atoi(inputBuffer);
      }

      if (c == '\n' || c == '\r')
      {
        int retValue = numberIndex;
        numberIndex = 0;
        return retValue;
      }
    }
  }
  return -1;
}

Also immer gleich am Ende der Zahl wandeln und nicht erst wenn der ganze String eingelesen wurde

Oder ganz ohne char Array:

int readSerial()
{
  static byte numberIndex;
  static bool parsing;

  while (Serial.available())
  {
    if (parsing == false)
    {
      parsing = true;
      memset(numbers, 0, sizeof(numbers));
    }

    char c = Serial.read();

    if (c >= '0' && c <= '9' && numberIndex < MAX_NUMBERS)
    {
      numbers[numberIndex] *= 10;
      numbers[numberIndex] += c - '0';
    }
    if (c == ';' || c == '\n' || c == '\r')
    {
      if (numberIndex < MAX_NUMBERS)
        numberIndex++;

      if (c == '\n' || c == '\r')
      {
        parsing = false;
        int retValue = numberIndex;
        numberIndex = 0;
        return retValue;
      }
    }
  }
  return -1;
}

Die Version geht dann nur für positive Zahlen, aber das kann man auch mit etwas Logik auf negative Zahlen erweitern.

Nicht 100%ig getestet. Kann sein dass da noch Bug drin sind :slight_smile: