Array aus App im Arduino-WiFi-Code weiterverarbeiten

Hallo zusammen,

ich lasse mir per App einen Array an mein Arduino Uno WiFi Rev2 schicken.
Das sieht dann im serial Monitor des Arduino so aus:

GET /Z[%2223%22,%20%2241%22,%20%2244%22,%20%2225%22,%20%2227%22,%20%2245%22,%20%2234%22,%20%2249%22,%20%2250%22,%20%22%22] HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 8.0.0; SHIFT6m Build/O00623)
Host: 192.168.0.14
Connection: Keep-Alive
Accept-Encoding: gzip

Der Array enthält die Werte [23,41,44,25,27,45,34,49,50] (oben grün hervorgehoben).

Was ich gar nicht verstehe ist, wie ich dann im Arduino-Code auf diesen Array zugreifen kann, um z.B. mit den einzelnen Einträgen des Arrays etwas zu machen. Ich verstehe einfach diesen Wirrwarr aus %-Zeichen und der Zahl 22 nicht.

Kann mir jemand helfen?

Viele Grüße

Das "%" steht vor einem Hexwert, der Text sieht also so aus:

GET /Z["23", "41", "44", "25", "27", "45", "34", "49", "50", ""] HTTP/1.1

Eine Aufteilung gelingt beispielsweise nach Vorbehandlung mit strtok.

String msg = "GET /Z[%2223%22,%20%2241%22,%20%2244%22,%20%2225%22,%20%2227%22,%20%2245%22,%20%2234%22,%20%2249%22,%20%2250%22,%20%22[]%22] HTTP/1.1";

void setup() {
  Serial.begin(115200);
  Serial.println(F("\nProgrammstart"));
  Serial.println(msg.indexOf('['));
  Serial.println(msg.lastIndexOf(']'));
  msg = msg.substring(1 + msg.indexOf("["), msg.lastIndexOf(']'));
  Serial.println(msg);
  msg.replace("%22", "");
  msg.replace("%20", "");
  msg.replace(",[]", "");
  Serial.println(msg);
  char * str = msg.c_str();
  char * pch;
  pch = strtok (str, ",");
  while (pch != NULL)
  {
    Serial.print(pch);
    Serial.print('\t');
    Serial.println(atoi(pch));
    pch = strtok (NULL, " ,.-");
  }
}

void loop() {}

PS: Eine Kompiler-Warnung habe ich jetzt mal ignoriert, es geht mir nur um eine Anregung.

ich lasse mir per App einen Array an mein Arduino Uno WiFi Rev2 schicken.

warum nicht als Parameter, also mit einem Fragezeichen vor den ganzen Werten?

agmue:
Das "%" steht vor einem Hexwert, der Text sieht also so aus:

GET /Z["23", "41", "44", "25", "27", "45", "34", "49", "50", ""] HTTP/1.1

Eine Aufteilung gelingt beispielsweise nach Vorbehandlung mit strtok.

String msg = "GET /Z[%2223%22,%20%2241%22,%20%2244%22,%20%2225%22,%20%2227%22,%20%2245%22,%20%2234%22,%20%2249%22,%20%2250%22,%20%22[]%22] HTTP/1.1";

[/quote]

Hallo,

vielen Dank für die Antwort. Die Frage, die sich mir stellt, ist allerdings, wie denn der Name von dem Array, in dem [%2223%22,%20%2241%22,%20%2244%22,%20%2225%22,%20%2227%22,%20%2245%22,%20%2234%22,%20%2249%22,%20%2250%22,%20%22%22] drinsteht, intern heißt. Der String, der von der App gesendet wird, ist ja jedesmal mit anderen Zahlen befüllt. Ich müsse also string msg = Name des Array schreiben müssen, um den Array dann auszulesen. Ich kann ja nicht pauschal String msg = "GET /Z[%2223%22,%20%2241%22,%20%2244%22,%20%2225%22,%20%2227%22,%20%2245%22,%20%2234%22,%20%2249%22,%20%2250%22,%20%22%22] HTTP/1.1"; definieren. Das muss ja variabel sein.

Viele Grüße

das ist kein Array sondern steht in der String Variable msg inkl. GET und HTTP/1.1 daher musst du des zerteilen.
erst danach hast du zugriff auf die einzelnen Daten wie im Beispiel von Agmue.

Warum schickst du die Werte nicht als Parameter?

Ah ok. Danke. Verstanden.

Warum schickst du die Werte nicht als Parameter?

Ich nutze diesen "MIT App Inventor 2" und ich weiß gar nicht, wie man von dort einen Parameter schickt, bzw. was ein Parameter genau ist.

Viele Grüße

noiasca:
das ist kein Array

Nach URL Decode ist es ein Json Array.

Behaupte ich mal!

Gruß Fips

Hallo nochmals,

also derzeit zieht mein Code folgendermaßen aus. Im Serial Monitor erhalte ich dann je nach Eingabe in der App folgenden Zeichencode beim plotten von dem char c:

GET /Z[%2223%22,%20%2241%22,%20%2244%22,%20%2225%22,%20%2227%22,%20%2245%22,%20%2234%22,%20%2249%22,%20%2250%22,%20%22%22] HTTP/1.1

Ich bin aber immer noch nicht schlau daraus geworden, wie ich denn jetzt z.B. den Zahlenvektor vektor=[23,41,44,25,27,45,34,49,50] aus diesem String herausfiltern kann.

Gibt es da keine einfache Lösung?

Grüße

#include <SPI.h>
#include <WiFiNINA.h>
#include <Servo.h>

#include "arduino_secrets.h" 

int lControl = 13;
char ssid[] = "blablabla";
char pass[] = "123456";
int keyIndex = 0;

Servo myServo;

int status = WL_IDLE_STATUS;

WiFiServer server(80);

void setup() {
// Pin 9 wird der Pin für den Servo sein
myServo.attach(9);
// Pin 13 wird ein Output-Pin für die LED sein
pinMode(13,OUTPUT);
// Serielle Schnittstelle initialisieren und warten, bis der Port geöffnet ist
Serial.begin(9600);
while (!Serial) {
;    //Warte, bis die serielle Schnittstelle verbunden ist
}

// Wenn die Kommunikation mit dem WiFi-Modul fehltschlägt, dann Meldung
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
while (true);
}

// Wenn die aktuelle Firmware-Version veraltet ist, dann Meldung, dies zu beheben
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
  Serial.println("Please upgrade the firmware");
}

// Wenn Kommunikation mit dem WiFi-Modul erfolgreich etabliert ist, dann Meldungen zu WiFi ausgeben
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(10000); 
}  
// start listening for incoming connections (start listening for clients) 
server.begin();
printWifiStatus();
}

void loop() {
// listen for incoming clients
WiFiClient client = server.available();
if (client) {
  // an http request ends with a blank line
  String currentLine= "";
  //boolean currentLineIsBlank = true;
  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      
      Serial.write(c);

      // if you've gotten to the end of the line (received a newline
      // character) and the line is blank, the http request has ended,
      // so you can send a reply
      if (c == '\n') {
        // send a standard http response header
        if (currentLine.length() == 0) {
        client.println("HTTP/1.1 200 OK");
        client.println("Content-Type:text/html");
        client.println();  // the connection will be closed after completion of the response
        client.print("Value at A0 is ");  // refresh the page automatically every 5 sec
        client.print(analogRead(A0));
        client.print("
");
        client.println();
        break;
      }
      else {
        currentLine = "";
      }
      } else if (c != '\r') {
        // you've gotten a character on the current line
        currentLine += c;
      }
      if (currentLine.endsWith("GET /H")) {
        digitalWrite(13, HIGH);
      }
      if (currentLine.endsWith("GET /L")) {
        digitalWrite(13, LOW);
      }
      if (currentLine.endsWith("GET /Z")) {
      }
    }
  }
  client.stop();
}
}

void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Was passiert, wenn Du eine Zeile ergänzt:

         else {
            Serial.println(currentLine);
            currentLine = "";
          }

agmue:
Was passiert, wenn Du eine Zeile ergänzt:

         else {

Serial.println(currentLine);
            currentLine = "";
          }

Dann printet er doppelt

oppaernst:
Dann printet er doppelt

Gut, dann kannst Du an der Stelle meinen Code aus #1 einbauen, nur anstelle msg eben currentLine.

agmue:
Gut, dann kannst Du an der Stelle meinen Code aus #1 einbauen, nur anstelle msg eben currentLine.

Danke schonmal. Habe den Code eingefügt, bekomme jetzt aber so kryptische Meldungen:

Please upgrade the firmware
Attempting to connect to SSID: Sonnenberg
SSID: Sonnenberg
IP Address: 192.168.0.14
signal strength (RSSI):-74 dBm
GET /Z[%22[]%22] HTTP/1.1
w)C⸮BF⸮{k{⸮⸮⸮[⸮⸮⸮⸮⸮⸮\⸮⸮L⸮	IQդ⸮F"!⸮!⸮n⸮>⸮⸮n⸮⸮⸮⸮w⸮⸮⸮{ke⸮⸮⸮⸮{⸮⸮{⸮k⸮{⸮⸮{k2B⸮⸮R⸮⸮⸮"⸮9 ⸮⸮P⸮)b'ǿ~⸮#S⸮\⸮⸮N⸮:⸮⸮B⸮4⸮⸮⸮⸮⸮⸮⸮D1x⸮⸮⸮7⸮⸮7⸮~E1ۗ⸮⸮⸮⸮{1⸮

Ok es scheint jetzt zu gehen. Habe den Befehl Serial.begin(115200); auskommentiert.

Jetzt erhalten ich ziemlich viele Meldungen aber unter anderem auch meine Zahlen.
Ist es korrekt, dass die da 2x nebeneinander vertikal stehen? Oder ist da irgendwas doppelt gemoppelt?

GET /Z[%2248%22,%20%2234%22,%20%2222%22,%20%2244%22,%20%2217%22,%20%2218%22,%20%223%22,%20%2240%22,%20%2246%22,%20%22%22] HTTP/1.1

Programmstart
6
122
%2248%22,%20%2234%22,%20%2222%22,%20%2244%22,%20%2217%22,%20%2218%22,%20%223%22,%20%2240%22,%20%2246%22,%20%22%22
48,34,22,44,17,18,3,40,46
48 48
34 34
22 22
44 44
17 17
18 18
3 3
40 40
46 46
User-Agent: Dalvik/2.1.0 (Linux; U; Android 8.0.0; SHIFT6m Build/O00623)

Programmstart
-1
-1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 8.0.0; SHIFT6m Build/O00623)
User-Agent: Dalvik/2.1.0 (Linux; U; Android 8.0.0; SHIFT6m Build/O00623)
User-Agent: Dalvik/2.1.0 (Linux; U; Android 8.0.0; SHIFT6m Build/O00623) 0
Host: 192.168.0.14

Programmstart
-1
-1
Host: 192.168.0.14
Host: 192.168.0.14
Host: 192.168.0.14 0
Connection: Keep-Alive

Programmstart
-1
-1
Connection: Keep-Alive
Connection: Keep-Alive
Connection: Keep-Alive 0
Accept-Encoding: gzip

Programmstart
-1
-1
Accept-Encoding: gzip
Accept-Encoding: gzip
Accept-Encoding: gzip 0

oppaernst:
Ist es korrekt, dass die da 2x nebeneinander vertikal stehen? Oder ist da irgendwas doppelt gemoppelt?

Erste Spalte die Zeichenkette, zweite die Zahl. Wenn es sich nicht unterscheidet, ist es gut!

Hallo,

mit Hilfe der im Code stehenden "void loop" lasse ich mir bei "GET /M" einen Vektor mit Zufallszahlen per App ans Arduino schicken. Anschließend wird dieser String dann in einen Vektor gewandelt, mit dem ich eigentlich weiterarbeiten will. Leider loopt die void danach noch 3 weitere male durch, sodass der Vektor pch am Ende dann doch wieder leer ist und ich die Zufallszahlen nicht weiterverarbeiten kann. Gibt es
eine Möglichkeit den Vektor pch irgendwie direkt "sicher abzulegen", bevor er wieder genullt wird?

Grüße

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//        VOID LOOP
//
void loop() {
//  
//
//  1.)
WiFiClient client = server.available();                                       // Abfrage, ob WiFi-Client verfuegbar ist
  if (client) {                                                               // Wenn der Client verfuegbar ist, dann
  String currentLine= "";                                                     // einen leeren String namens currentLine anlegen
//
    while (client.connected()) {                                              // waehrend der Client verfuegbar ist, tue
      if (client.available()) {                                               // wenn der Client verfuegbar ist, dann
        char c = client.read();                                               // in c wird die Info, die aus dem Client kommt, geschrieben
//
          if (c == '\n') {                                                    // wenn ein Newline-Character auftritt ... 
            if (currentLine.length() == 0) {                                  // ...und die Laenge des Newline-Characters Null ist
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type:text/html");
              client.println();  // the connection will be closed after completion of the response
              client.print("Value at A0 is ");  // refresh the page automatically every 5 sec
              client.print(analogRead(A0));
              client.print("
");
              client.println();
              break;
              }
           else {
//
  Serial.println(F("\nProgrammstart"));
  Serial.println(currentLine.indexOf('['));
  Serial.println(currentLine.lastIndexOf(']'));
  currentLine = currentLine.substring(1 + currentLine.indexOf("["), currentLine.lastIndexOf(']'));
  Serial.println(currentLine);
  currentLine.replace("%22", "");
  currentLine.replace("%20", "");
  currentLine.replace(",[]", "");
  Serial.println(currentLine);
  char * str = currentLine.c_str();
  char * pch;
  pch = strtok (str, ",");
  while (pch != NULL)
  {
    Serial.print(pch);
    Serial.print('\t');
    Serial.println(atoi(pch));
    pch = strtok (NULL, " ,.-");
    }       
//
//                      
             currentLine = "";
             }
           } else if (c != '\r') {                                             // wenn ein Character in der current line ist, dann
              currentLine += c;                                                // currentLine = currentLine +c
              }
//
//              
if (currentLine.endsWith("GET /H")) {                                          // wenn die aktuelle Line mit /H endet, dann Test-LED an
          digitalWrite(13, HIGH);
}                                                                              // Ende der Schleife
//
//
//        
if (currentLine.endsWith("GET /L")) {                                          // wenn die aktuelle Line mit /L endet, dann Test-LED aus
          digitalWrite(13, LOW);
   }
//
//
//
if (currentLine.endsWith("GET /M")) {                                          // wenn die aktuelle Line mit /L endet, 
}
//
//
//       

//currentLine = "";
//
//
//      
   }                                                                           // Ende if client available
  }                                                                            // Ende if client connected                               
 }                                                                             // Ende if client
client.stop();                                                                 // Client stop
//Serial.println("check");
}

Habs mit einem counter gelöst:

  if (counter ==1) {
  Serial.println(F("\nProgrammstart"));
  Serial.println(currentLine.indexOf('['));
  Serial.println(currentLine.lastIndexOf(']'));
  currentLine = currentLine.substring(1 + currentLine.indexOf("["), currentLine.lastIndexOf(']'));
  Serial.println(currentLine);
  currentLine.replace("%22", "");
  currentLine.replace("%20", "");
  currentLine.replace(",[]", "");
  Serial.println(currentLine);
  char * str = currentLine.c_str();
  char * pch;
  pch = strtok (str, ",");
  while (pch != NULL)
  {
    Serial.print(pch);
    Serial.print('\t');
    Serial.println(atoi(pch));
    pch = strtok (NULL, " ,.-");
    }
  }
  counter=counter+1;

Grüße

agmue:
Erste Spalte die Zeichenkette, zweite die Zahl. Wenn es sich nicht unterscheidet, ist es gut!

Hallo,

gibt es denn die Möglichkeit, die ermittelten Zahlen als global zu speichern, sodass auf diese jederzeit zugegriffen werden kann?

Grüße

oppaernst:
Anschließend wird dieser String dann in einen Vektor gewandelt,

Meinst Du c_str oder Zeiger?

oppaernst:
Leider loopt die void ...

"void" bedeutet, die Funktion hat keinen Rückgabewert. Anstelle von void kann auch ein Typ stehen wie byte testfunktion() {...}. Die Funktion loop() wird als Schleife ständig wiederholt, sagt ja der Name.

oppaernst:
Habs mit einem counter gelöst:

Wenn Du den counter Schrittzähler nennst, könnte das Dein Einstieg in die bewußte Nutzung einer Schrittkette (=endlicher Automat, =finite state machine) sein.

oppaernst:
gibt es denn die Möglichkeit, die ermittelten Zahlen als global zu speichern, sodass auf diese jederzeit zugegriffen werden kann?

Ja.

Bei guten Programmierern sind globale Variablen aber nicht so beliebt. Da übergibt man Informationen lieber als Zeiger oder Referenzen, um Funktionen als gekapselte Einheiten betrachten zu können.