Estrarre una stringa da client.read

Buongiorno! Nonostante il mio codice sia terminato nella struttura ed in fase di test... ogni volta che lo riapro mi vengono in mente sempre piccole aggiunte che potrei fare :) In particolare avrei bisogno di un consiglio su come fare questa cosa:

Dopo aver inviato i dati a pachube ottengo una risposta che stampo a seriale con questo codice:

 while(client.connected())
    {
      // stay in this loop until the server closes the connection
      while(client.available())
      {
        //client.read();
        char c = client.read(); //gets byte from ethernet buffer
        Serial.print(c); //prints byte to serial monitor 
      }
    }

Ed ottengo, per la maggior parte dei casi, una cosa così:

HTTP/1.1 200 OK Date: Sun, 26 Feb 2012 10:05:29 GMT Content-Type: text/plain; charset=utf-8 Connection: close X-Pachube-Logging-Key: logging.xxxxxxxxxxxxxxxx X-PachubeRequestId: xxxxxxxxxxxxxxxxxxxxxxxxxx Cache-Control: max-age=0 Content-Length: 1 Age: 0 Vary: Accept-Encoding

Questo messaggio è fondamentale perché, oltre a svuotare il buffer di ricezione della eth shield (per cui basterebbe un client.read() ) mi permette di vedere lo status di pachube e capire se eventuali malfunzionamenti dipendono da me o da loro.

Quello che vorrei fare è raccogliere dal client.read() i caratteri dal 10 al 15. In pratica estrarre solo "200 OK" e memorizzarlo in una variabile di 5 caratteri da pubblicare sulla pagina del webserver. Voglio proprio solo 5 caratteri, il resto può essere allegramente troncato :) Questo mi permetterebbe di avere un debug anche se non sono connessa tramite pc.

La lista di errori di pachube è varia, ma a me bastano quei cinque caratteri in quella posizione (la stringa HTTP/1.1 è costante).

Suggerimenti per come fare? Ah dimenticavo la parte difficile... abbiamo solo 0.5 k di sketch e 216 di FREERAM :P Lo spazio di sketch posso eventualmente aumentarlo mettendo il bootloader della UNO ma mi piacerebbe mantenere il progetto dentro una duemilanove.

Grazie! :)

DanielaES:       while(client.available())       {         //client.read();         char c = client.read(); //gets byte from ethernet buffer         Serial.print(c); //prints byte to serial monitor       }     }

Na robetta cosi' ?

char c = Conn_1.read(); Testo1.concat(c) ; if (Testo1.endsWith(FineRiga)) { Serial.print("R1 : "); Serial.print(Testo1); Testo1 = "" ; }

Testo1 e' una String

FineRiga sono i caratteri \r\n o quelli che ti aspetti alla fine della stringa

ciao

ti crei un piccolo array di char[] e vi memorizzi i caratteri quando li ricevi, fino ad un certo valore massimo che è la dimensione dell'array. A quel punto, fuori dal ciclo di ricezione, fai un confronto tra il contenuto dell'array e la stringa che ti aspetti usando strcmp()

brunol949:
Na robetta cosi’ ?

Se ho capito bene il tuo codice…

while(client.available())
      {
        //client.read();

        char c = client.read(); //gets byte from ethernet buffer
        Serial.print(c); //prints byte to serial monitor 
        String Testo1;
        Testo1.concat(c) ;
        if (Testo1.endsWith("\r\n")) {
          Serial.print("R1 : ");
          Serial.print(Testo1);
          Testo1 = "" ; 
        }

      }

Questa robetta occupa 1.4 k!! Sketch too big… serve qualcosa di più ottimizzato :
Tra l’altro in questo modo mi pare di capire che Testo1 conterrebbe tutta la prima riga, compreso l’HTTP ecc… che io volevo scaricare perché nn mi serve.

@Luca qualche esempio?

ciao

(codice non provato, dovrebbe cmq essere ok):

#define BUFFER_SIZE 7
char rxbuffer[BUFFER_SIZE];
int buffer_position = 0;
int char_count = 0;

while(client.connected())
    {
      while(client.available())
      {
		char c = client.read();
		Serial.print(c);		
		
		if(char_count > 8 && char_count < 15) rxbuffer[buffer_position++] = c;
                char_count++;
      }
    }	
rxbuffer[buffer_position] = '\0';
if(strcmp(rx_buffer, "200 OK") == 0) Serial.println("OK!")
else Serial.println("KO!);
  • definisci un buffer di 7 caratteri (“200 OK” sono 6 caratteri + il terminatore \0 di stringa alla fine)
  • tieni un indice che ti conta i caratteri ricevuti dal client e uno che tiene la posizione in cui stai scrivendo nel buffer
  • se stai ricevendo i caratteri dal 9 al 14 li salvi nel buffer spostando avanti di uno il puntatore della posizione
  • incrementi il contatore caratteri
  • alla fine del ciclo aggiungi il terminatore di stringa
  • confronti il buffer ricevuto con la stringa che ti aspetti

fammi sapere se funziona!

Luca, che dire, complimenti! Il codice è perfetto, fa esattamente quello che volevo ed occupa solo 84 byte di sketch!! ( e 7 byte di ram). Non ho messo strcmp perché ho già una variabile " ok - ko ", in questo caso volevo vedere proprio il codice di risposta ed, eventualmente, di errore :)

Viste le differenze di dimensioni tra le soluzioni proposte inizio a pensare che se IO sapessi programmare probabilmente sarei riuscita a fare stare tutto il mio progetto in un solo arduino, anziché usarne due :) Dio solo sa quante risorse sto sprecando... All'inizio, per risolvere questa questione della stringa, avevo impostato un for da 2.5 k!

Che poi ogni volta che penso che la mia sim del cellulare ha 256k e che io sto a lavorare per stare dentro ad uno 0.4 k... mi vien da ridere e mi fa riflettere :)

Btw luca, istruiscimi un attimino: Perché usi il define?

#define BUFFER_SIZE 7
char rxbuffer[BUFFER_SIZE];

che vantaggi ha rispetto ad un banale:

char rxbuffer[7];

?

Ed in ogni caso... grazie! Ho ancora quasi 0.4k per pensare di metterci qualcos'altro, oramai questo arduino lo sto farcendo come un tacchino :)

Il problema dell'aumento delle dimensioni è dato dal fatto che appena dichiari

String testo1;

il compilatore carica tutto il codice della libreria necessario per quel comando. E' che magari non è necessario perché puoi ottenere lo stesso risultato in altro modo.

Il #define BUFFER_SIZE 7 è usato per modificare la lunghezza del buffer comodamente all'inizio del programma senza andare a cercarsi la variabile in tutto il codice. Un pò come si fa per definire i pin su cui sono mappati i sensori. La sostituzione avviene prima della compilazione e non comporta l'aumento della dimensione del codice oggetto.

Ciao

confermo quanto ha scritto Paolo: l'uso dei define è comodo per cambiare "in corsa" eventuali valori, senza spulciare tutto il codice per sostituirli... essendo - a differenza delle variabili - sostituiti dal compilatore non ti utilizzano RAM o PROGMEM.

Ciao a tutti io avrei un problema simile ma credo piu semplice e quindi spero mi possiate aiutare, io tramite il codice: char c = client.read(); ottengo dei valori che invio da un server creato in labview ma li vorrei come un array char quindi la domanda è: come converto i valori che arrivano in un array char?

grazie mille a tutti

Se conosci la lunghezza dei caratteri in arrivo li leggi con un for. Altrimenti con un while con condizione di uscita. All'interno del ciclo ti crei l'array con i dati in arrivo incrementando un indice di posizione all'interno dell'array per ogni dato letto.

Hai riesumato un topic di 2 anni fa. :drooling_face:

Difatti ha poi aperto un thread apposito :sweat_smile:

azz, pensavo che fosse tornato il tipo.... :sweat_smile: