Uso libreria Stream e readtString

BigByte:
Ciao, non credi che cosi corri il rischio di usare tutta la memoria? e se per lo stop del loop ti fai mandare il numero di caratteri che il client intende inviare?

Ciao

Certo che corro il rischio... è tutto in prova.

Se non erro, client.available() dovrebbe fare ciò che dici nella seconda domanda giusto?
Mi ritorna sempre 0...

le stringhe anno potenzialmente lunghezza infinita. Non so come lavora lo shield, ma in teoria ilpacchetto TCP arriva con un MTU noto (lughezza massima del pacchetto, quindi un messaggio più lungo viene spezzato in più pacchetti, e può capitare che venga spezzato in pacchetti più picoli se una parte della rete usa MTU più piccoli). normamente l'MTU è di 1500byte, quindi credo che sia infattibile di base per l'arduino.

non usare endsWith ma leggi byte per byte, considerando che stai implementando a partire dal TCP, ti convene creare un tuo protocollo, e quindi decidi tu la lughezza massima e vari altri parametri. Internet è una brutta bestia, devi fare molta attenzione se esci dalla rete locale.
Il mio approccio in questi casi è chiudere la connessione al minimo errore.

lesto:
non usare endsWith ma leggi byte per byte, considerando che stai implementando a partire dal TCP, ti convene creare un tuo protocollo, e quindi decidi tu la lughezza massima e vari altri parametri. Internet è una brutta bestia, devi fare molta attenzione se esci dalla rete locale.
Il mio approccio in questi casi è chiudere la connessione al minimo errore.

Sto provando con la libreria textfinder, che fa tutto byte per byte....
Mi semplifica molto la cosa ma... per ora non mi funge la getstring

Ho cambiato il codice del primo post a favore dell'uso delle funzioni offerte dalla libreria TextFinder (Arduino Playground - TextFinder) che lavora byte by byte

void parse()
{
  //String myAvviso = ""; 
  char myAvviso[500];
  Serial.println("Parsing");
  if (finder.find("title") && finder.getString("title","studenti",myAvviso,500))
  { 
    Serial.println("Avviso trovato!");
    //finder.getString("title","publishing",myAvviso,100);
    Serial.println("Avviso: ");
    Serial.println(myAvviso);     
  }
  else 
  {    
    Serial.println("Failed parsing...");
   // client.stop();
  }
}

Il mio problema adesso è che ho bisogno di un buffer molto grande (quindi torniamo al problema di prima) per contenere tanto testo compreso tra "title" e "studenti".
L'array di char è troppo piccolo, e se lo aumento inizio ad avere problemi.

Consigli?

Secondo me manca sempre nelle domande.

"vorrei fare con una ethernet e un display .............ecc " (piccolo riassunto del risultato che si vuole ottenere)

pablos:
Secondo me manca sempre nelle domande.

"vorrei fare con una ethernet e un display .............ecc " (piccolo riassunto del risultato che si vuole ottenere)

Devo realizzare una specie di rss reader, l'hardware da me utilizzato è questo: http://arduino.cc/forum/index.php/topic,126220.0.html

Mi sono messo in contatto con chi ha scritto la libreria TextFinder e mi ha detto che le funzioni sono state migliorate e incluse nel core di arduino dalla versione dell'ide 1.0 (mi pare) in poi.
Mi ha consigliato di usare la funzione readString però non ho trovato molta documentazione sulla libreria Stream: Stream - Arduino Reference
Infatti non c'è la readString tra la documentazione, sono costretto a spulciare il file sorgente all'interno del core per vedere come e cosa fa....
...male non mi fa! :slight_smile:

dovremmo fare una copia del reference sul palyground e sistemarlo per bene..
ci sono un sacco di funzioni interessanti non documentate

lesto:
dovremmo fare una copia del reference sul palyground e sistemarlo per bene..
ci sono un sacco di funzioni interessanti non documentate

Quindi non mi ero sbagliato che mancano un pò di funzioni nuove sul reference?!

Mi sono letto 4/5 volte QUELLA pagina e non riuscivo a trovare readString(), pensavo di avere qualche problema di lettura.... lettura dei miei occhi... :.

e se modifichi il metodo getString aggiungendo da quale punto vuoi iniziare a leggere, provo a fare un esempio

//questo nella libreria
int TextFinder::getString( char *pre_string, char *post_string, char *buffer,int start, int length)
  {  
    if( find(pre_string) ){ 
      int index = 0;   
      *buffer = 0;
      while(index < length-1 ){
        
		char c = myRead();
		
		if(start == 0)
		{        
			if( c == 0 ){
				return 0;   // timeout returns 0 !
			}
			else if( c == *post_string ){
				buffer[index] = 0; // terminate the string
				return index;               // data got successfully
			}
			else{
				buffer[index++] = c;   
			}
		}
		else
		{
			start--;
		}
      }
	  
      buffer[index] = 0;
      return index; // Note: buffer full before the closing post_string encountered
    }   
    return 0;    //failed to find the prestring
  } 

// le tuo codice fai una cosa tipo
 
char myAvviso[500];
  int len = 0;  
  
  while (client.available()) {             
	len = len + finder.getString("title","studenti",myAvviso,len,500);
	--aggiungo myAvviso[] i in una memoria + grande esempio SD 
  }

non so se funziona non l'ho provato ma vedi se può esserti utile

visto che la mole di dati probabilmente non ti starà in memoria, la soluzione è avere un piccolo buffer circolare; immagino che ci sia un tag particolare che cerchi per individuare l'inizio e la fine dei messaggi che ti interessano.

a questo punto hai 2 stati da gestire:

stato 1: riempi len(tagInizio) buffer e cerchi il tag di inizio. Se lo trovi carichi il buffer fino a quando il tag di inizio non ne esca ed entri nello stato 2
stato 2: cerchi il tag di fine. copi il contenuto del buffer fino alla fine o all'eventiale tag di fine in una string. Se hai trovato il tag di fine, elimina l'eventuale parziale di tag fine ed elabora la stringa ed entra nello stato 1. se non la trovi, riempi il buffer di len(tagFine) (ricordati da dove sei arrivato a salvare eh!) e ricomincia lo stato 2

in questo modo con un piccolo buffer (grande almeno quanto il massimo tra la lungheza id tag di inizio e di tag fine) sei in grado di leggere infiniti mesaggi. Sta a te a questo punto fare in modo che i mesaggio salvato durante la fase 2 non sfondi la ram. per esempio puoi dire che a priori lo stato 2 non può leggere più di X lettere, e quindi esce anche in caso di tag fine on trovato ma limite raggiunto.

oppure non salvi ed elabori la stringa completa, ma elabori ad ogni stato2 la stringa parziale col rischio però di elaborare anche il tag fine quando ti arriva parziale. per eliminare il problema ad ogni lettura viene eseguita la stringa precedente se il tag fine non viene trovato, altrimenti si triggera il cambio stato a 1 che si occupa di eliminare il tag fine e ricrearti il partziale del turno precedente+questo turno pulito del tag

lesto:
in questo modo con un piccolo buffer (grande almeno quanto il massimo tra la lungheza id tag di inizio e di tag fine) sei in grado di leggere infiniti mesaggi.

E' proprio quello che sto cercando di fare da qualche giorno!
Ma un pò per la scarsa documentazione, un pò per i limiti hardware e software, un pò per piedinature comuni (vedi l'altro post), ancora non sono riuscito a realizzare ciò.

Il problema che mi/vi pongo è:
Se il messaggio tra tag inizio e tag fine è bello lungo.... diciamo 1000char, rischio overflow?
O meglio, cosa succede all'arduino se durante l'esecuzione cattura una stringa tale da far andare in overflow la ram? si resetta? tronca? non compila? cosa fa in running?
Vorrei capire questo particolare in modo tale da accorgermi se qualcosa non va.

BigByte:
e se modifichi il metodo getString aggiungendo da quale punto vuoi iniziare a leggere, provo a fare un esempio

Grazie per l'aiuto!

Come ho scritto prima, questi metodi sono stati modificati e migliorati nella classe Stream.
Credo che utlizzerò queste funzioni con qualche idea che mi è venuta prima e che ho scritto poche righe più su.

...forse è meglio cattuare la stringa a gruppi di Xchar, stamparli, ricatturare Xchar da Xchar+1
fino al tag di fine e amen...

un pò più macchinoso ma mi evito problemi di overflow

che succede se il tag rimane a metà tra una lettura e l'altra? per questo tiro in mezzo i buffer. :stuck_out_tongue:

Se il messaggio tra tag inizio e tag fine è bello lungo.... diciamo 1000char, rischio overflow?

sì, se va bene crasha e si resetta, se va male finisce in qualche loop infinito, oltre se comportamenti a random.
Se credi di avere messaggi lunghi, compra una ram esterna i2c. cerca FRAM, ce ne sono pure da 256kB...

Ok, fatto.
La readString non mi restituisce nulla, credo vada in overflow (?).
Mentre la readBytes torna quello che devo tornare.
Ora con il buffer (di mille!!!) pieno posso giocare come voglio...

Lascio il codice per chi un giorno cercherà su google queste funzioncine:

void parse()
{
  //client.setTimeout(10000);  //opzionale
  //String myAvviso; 
  char myAvviso[1000];
  Serial.println("Parsing");
  if (client.find("title")) //se trovo il tag di inizio *title*...
  { 
    Serial.println("Avviso trovato!");
    //myAvviso=client.readString();
    client.readBytes(myAvviso, 1000); //metti 1000 char nel buffer
    Serial.println("Avviso: ");
    Serial.println(myAvviso);   
  }
  else 
  {    
    Serial.println("Failed parsing...");
  }
}

PS
Posso convertire quel buffer di char nell'oggetto String? Con i metodi di String mi risparmio qualche riga di codice...

char alloca la ram dinamicamente, rischi seriamente di avere problemi di allocazione dello spazio

lesto:
char alloca la ram dinamicamente, rischi seriamente di avere problemi di allocazione dello spazio

infatti il cast non funge... lavorerò con i char

il cast?? nono vabbè

prova a usare sempre i char ma con una realloc, in modo da rendere l'array dinamico. Solo non fare come la string che alloca giusto quello che gli serve ma alloca chessò, 100 byte alla volta. In teoria se dopo la prima malloc NON crei nuove variabili dovresti riuscire sempre fino a ram overflow

lesto:
char alloca la ram dinamicamente,

perchè dici dinamicamente?
char[100] è un array statico. erro?

sì, ma se poi lo riallochi, allora può essere considerato dinamico

edit: e non sarà più un array ma un puntatore