Problema con le stringhe

Buongiorno ragazzi,
oggi sto impazzendo con le stringhe.

Di seguito potete trovare il risultato che ottengo nella seriale e il codice che ho scritto.

Una volta che si avvia lui mi assegna in modo corretto il contenuto che va all'interno della variabile stringa denominata "strdati" e invia la richiesta al server.

Quando lo riesegue dopo circa 15s la variabile "strdati" risulta vuota se pur il blocco di assegnazione è uguale a quello utilizzato in precedenza.
Se sbaglio qualcosa, mi potete spiegare dove si trova l'errore.

  if (client.connect(server2, 80)) {
    Serial.println("");
    Serial.println("connected");
    client.println("POST /connect/nossl/cl_dc_ws.php HTTP/1.1");
    client.println("Host: www.prova.it");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.println("User-Agent: Arduino/1.0");
    client.print("Content-Length: ");
    Serial.println("Lunghezza = " + String(strdati.length()));
    Serial.println("--- Invio parametri ---");
    strdati = "";
    strdati = String("f=val&cod=" + matripro + "&p1=" + p1 + "&p2=" + p2 + "&p3=" + p3 + "&p4=" + p4 + "&p5=" + p5 + "&p6=" + p6 + "&p7=" + p7 + "&p8=" + p8 + "&p9=" + p9 + "&p10=" + p10 + "&p11=" + p11 + "&p12=" + p12 + "&p13=" + p13 + "&p14=" + p14 + "&p15=" + p15 + "&p16=" + p16 + "&p17=" + p17 + "&p18=" + p18 + "&p19=" + p19 + "&p20=" + p20 + "&p21=" + p21 + "&p22=" + p22 + "&p23=" + p23 + "&p24=" + p24 + "&p25=" + p25 + "&p26=" + p26 + "&p27=" + p27 + "&p28=" + p28 + "&p29=" + p29 + "&p30=" + p30 + "&p31=" + p31 + "&p32=" + p32 + "&p33=" + p33 + "&p34=" + p34 + "&p35=" + p35  + "&p36=" + p36 + "&p37=" + p37 + "&p38=" + p38 + "&p39=" + p39 + "&p40=" + p40 + "&p41=" + p41 + "&p42=" + p42 + "&p43=" + p43 + "&p44=" + p44 + "&p45=" + p45  + "&p46=" + p46 + "&p47=" + p47 + "&p48=" + p48 + "&p49=" + p49 + "&p50=" + p50 + "&p51=" + p51 + "&p52=" + p52 + "&p53=" + p53 + "&p54=" + p54 + "&p55=" + p55 + "&p56=" + p56 + "&p57=" + p57 + "&p58=" + p58 + "&p59=" + p59 + "&p60=" + p60 + "&p61=" + p61 + "&p62=" + p62 + "&p63=" + p63 + "&p64=" + p64 + "&p65=" + p65 + "&p66=" + p66 + "&p67=" + p67 + "&p68=" + p68 + "&p69=" + p69 + "&p70=" + p70 + "&p71=" + p71 + "&p72=" + p72 + "&p73=" + p73 + "&p74=" + p74 + "&p75=" + p75 + "&p76=" + p76 + "&p77=" + p77 + "&p78=" + p78 + "&p79=" + p79 + "&p80=" + p80 + "&p81=" + p81 + "&p82=" + p82 + "&p83=" + p83 + "&p84=" + p84 + "&p85=" + p85 + "&p86=" + p86 + "&p87=" + p87 + "&p88=" + p88 + "&p89=" + p89 + "&p90=" + p90 + "&p91=" + p91 + "&p92=" + p92 + "&p93=" + p93 + "&p94=" + p94 + "&p95=" + p95 + "&p96=" + p96 + "&p97=" + p97 + "&p98=" + p98 + "&p99=" + p99 + "&p100=" + p100 + "&p101=" + p101 + "&p102=" + p102 + "&p103=" + p103 + "&p104=" + p104 + "&p105=" + p105 + "&p106=" + p106 + "&p107=" + p107 + "&p108=" + p108 + "&p109=" + p109 + "&p110=" + p110 + "&p111=" + p111 + "&p112=" + p112 + "&p113=" + p113 + "&p114=" + p114 + "&p115=" + p115 + "&p116=" + p116 + "&p117=" + p117 + "&p118=" + p118 + "&p119=" + p119 + "&p120=" + p120 + "&p121=" + p121 + "&p122=" + p122 + "&p123=" + p123 + "&p124=" + p124 + "&p125=" + p125 + "&p126=" + p126 + "&p127=" + p127 + "&p128=" + p128 + "&p129=" + p129 + "&p130=" + p130 + "&p131=" + p131 + "&p132=" + p132 + "&p133=" + p133 + "&p134=" + p134 + "&p135=" + p135 + "&p136=" + p136 + "&p137=" + p137 + "&p138=" + p138 + "&p139=" + p139 + "&p140=" + p140 + "&p141=" + p141 + "&p142=" + p142 + "&p143=" + p143 + "&p144=" + p144);
    Serial.println(strdati);
    Serial.println("Lunghezza = " + String(strdati.length()));
    client.println(strdati.length());
    client.println();
    client.print(strdati);
    client.println();
    Serial.println("Fine invio richiesta");
  }

Credo che una possibile causa possa essere il valore di uno o più parametri incompatibile con la creazione dell'oggetto String, ad esempio (ma è solo un esempio in quanto non usando la classe String non ho abbastanza dimestichezza per indicare una specifica causa) un parametro con valore null magari fa fallire l'intera costruzione portando ad una stringa vuota.
Io farei stampare su seriale i valori di tutti i parametri coinvolti nella creazione della stringa per tentare di capire se e quale di questi ha un valore diverso rispetto alla prima chiamata (funzionante) e che possa causare l'anomalia nella seconda chiamata.
Come già detto e ridetto mille volte sul forum poi ti consiglio si evitare l'uso della classe String, specie nel tuo caso dove allochi e deallochi continuamente oggetti String in memoria, che inevitabilmente porterà a problemi di gestione delle memoria con blocchi improvvisi

Nella seriale mi sono fatto visualizzare il valore di tutte le variabili intere denominati con la P.
Tutti i parametri hanno per il momento il valore a 0.

Come ha già detto fabpolli, evita come la peste le variabili "String", tanto più se ne crei continuamente di nuove (anche se è la stessa variabile, se è definita dentro ad un loop viene riallocata ogni volta) e/o se devi fare molte manipolazioni e concatenazioni.

Nel tuo caso poi visto che i parametri sono tutti in sequenza, perché invece di fare 144 variabili (quali valori possono assumere? Dall'immagine pare siano solo 0 o 1, quindi puoi definirli byte, o meglio bool...) e quindi 144 parametri nell'URL, non imposti una sola variabile array con 144 elementi e quindi nella URL mandi UN solo parametro con la concatenzaione dei 144 caratteri 0 o 1 (tra l'altro facendo questo con un semplice for invece della sbrodolata di 144 concatenazioni...)? Ed in questo caso magari ti basta una semplice stringa da 144 caratteri (145 con lo \0)...

Sto valutando il vostro consiglio di non utilizzare le stringhe.
Il problema è quello che alcuni parametri sono boolean altri byte e altri ancora unsigned int.

fabio22:
Nella seriale mi sono fatto visualizzare il valore di tutte le variabili intere denominati con la P.
Tutti i parametri hanno per il momento il valore a 0.

Se vuoi posta il codice completo che magari il problema è altrove, perchè detta così escludendo che la memoria si sia già incastrata visto le 288 concatenazioni (che Arduino usi?) non vedo altre couse che mi danno possibilità di formulare altre ipotesi

Io utilizzo l'arduino mega e la variabile "strdati" viene utilizzata soltanto in quella routine.
L'esecuzione del software non si blocca.

fabio22:
Sto valutando il vostro consiglio di non utilizzare le stringhe.
Il problema è quello che alcuni parametri sono boolean altri byte e altri ancora unsigned int.

Il software lato server è tuo? Se si allora ti suggerirei di raggruppare per tipo le variabili in tre array in modo da poter inviarne i valori usando i parametri ma quantomeno usando cicli (for o while che sia) che renderebbe il codcie senzaltro migliore e più manuntenibile.
L'ipotesi di abbandonare l'oggetto String io la vedo più come un imperativo piuttosto che una cosa su cui occorre riflettere, alla fine sai quanti sono i parametri, i loro tipi e quindi la dimensione massima finale che la tua stringa potrà mai ottenere, definisci un array di char di tale dimensione e con le funzioni legate alle stringhe classiche, tre cicli e qualche if ottieni un risultato migliore e stabile nel tempo di esecuzione del codice che porterà ad un inevitabile robustezza del codice, cosa che con le String allocate e riallocate sicuramente non avrai mai anzi hai la certezza di andare incontro a blocchi impovvisi ed (apparentemente) immotivati

fabio22:
Io utilizzo l'arduino mega e la variabile "strdati" viene utilizzata soltanto in quella routine.
L'esecuzione del software non si blocca.

Non si blocca all'inizio :smiling_imp: fallo girare H24 7/7 e ogni 15 secondi spara qualcosa al server e vedrei che dopo alcuni minuti/ore tutto andrà in vacca

>fabio22: ti ricordo che NON sei su un PC dove c'è un sistema operativo ed un "garbage collector", sei su una piccola MCU (ATmega2560) con solo 4KBytes di SRAM, dove devi fare tutto tu e dove usare la classe "String", a causa dell'allocazione e riallocazione dinamica della memoria, porta quasi sempre ... a grossi problemi e sicuri mal di testa !!!

Impara ad usare le stringhe classiche del C ... ovvero semplici array di char terminati dal carattere null (0x00) e le funzioni che trovi nella libreria standard (... che, oltretutto, è automaticamente inclusa dal IDE) AVR libc ed, in particolare, quanto è in <string.h> :wink:

Guglielmo

Vi ringrazio per i consigli. Sicuramente approfondirò l'argomento.

fabio22:
Sto valutando il vostro consiglio di non utilizzare le stringhe.
Il problema è quello che alcuni parametri sono boolean altri byte e altri ancora unsigned int.

Ok, allora usa un array di unsigned int, che può contenerli tutti, ed usa una for() per concatenare i parametri dentro ad una stringa C (e non più "String", neanche come funzione...).

Una cosa del tipo (scritta al volo, eh, da verificare...):

...
unsigned int par[144];
char strdati[2000]; // Parametri per l'URL
char buf[20]; // Buffer di conversione valori interi

...
  if (client.connect(server2, 80)) {
    Serial.println("");
    Serial.println("connected");
    client.println("POST /connect/nossl/cl_dc_ws.php HTTP/1.1");
    client.println("Host: www.prova.it");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.println("User-Agent: Arduino/1.0");
    client.print("Content-Length: ");
    Serial.println("Lunghezza = " + String(strdati.length()));
    Serial.println("--- Invio parametri ---");

    strcpy(strdati, "f=val&cod=" + matripro);
    for (int i=0; i<144; i++)
    {
      strcat(strdati, "&p");
      itoa(i+1, buf, 20);
      strcat(strdati, buf);
      strcat(strdati, "=");
      itoa(par[i], buf, 20);
    }
    Serial.println(strdati);

    Serial.print("Lunghezza = ");
    Serial.println(strlen(strdati));

    client.println(strlen(strdati));
    client.println();
    client.print(strdati);
    client.println();

    Serial.println("Fine invio richiesta");
  }

Ti ringrazio per l'esempio.

Invece la mancata connessione al server da cosa può dipendere. Ho notato che alcune volte non si riesce a collegarsi al server per circa 3 - 4 richieste.

Una cosa per volta, anche perché non è detto che le cose non siano correlate.

Risolvi la questione delle stringhe/array, e quando quella funziona vedi se hai ancora problemi.

Ciao docdoc,
sto provando il tuo esempio.
Mi va ad occupare il 13% in più di memoria portandola all'81%.

Facendo per diverse ore alcune prove, ho notato che il problema menzionato all'inizio di questo TOPIC, lo fa nel momento in cui richiamo la pagina WEB Server.

Ragazzi, può essere che va in saturazione qualche buffer?

L'occupazione di memoria è tale da poter generare problemi quindi potrebbe dipendere anche da quello, posta il codice attuale completo che magari qualcosa salta all'occhio e/o qualcosa si può otimizzare per ridurre il consumo di memoria, inoltre qualcuno può aiutarti con maggior facilità se ha il codice da analizzare

Sto provando mandando tutti i parametri senza formare una stringa lunga e sembra funzionare regolarmente.

L'ho pensata di svilupparla tenendo in considerazione l'aiuto di "docdoc" nel modo seguente:

      for (int i = 1; i < 91; i++) {
        if (i == 1) {
          client.print("&p1=" + String(p1));
        }
        if (i == 2) {
          client.print("&p2=" + String(p2));
        }
        if (i == 3) {
          client.print("&p3=" + String(p3));
        }
        if (i == 4) {
          client.print("&p4=" + String(p4));
        }
        if (i == 5) {
          client.print("&p5=" + String(p5));
        }
        if (i == 6) {
          client.print("&p6=" + String(p6));
        }
        if (i == 7) {
          client.print("&p7=" + String(p7));
        }
        if (i == 8) {
          client.print("&p8=" + String(p8));
        }
        if (i == 9) {
          client.print("&p9=" + String(p9));
        }
        if (i == 10) {
          client.print("&p10=" + String(p10));
        }
        if (i == 11) {
          client.print("&p11=" + String(p11));
        }
        if (i == 12) {
          client.print("&p12=" + String(p12));
        }
        if (i == 13) {
          client.print("&p13=" + String(p13));
        }
        if (i == 14) {
          client.print("&p14=" + String(p14));
        }
        if (i == 15) {
          client.print("&p15=" + String(p15));
        }
        if (i == 16) {
          client.print("&p16=" + String(p16));
        }
        if (i == 17) {
          client.print("&p17=" + String(p17));
        }
        if (i == 18) {
          client.print("&p18=" + String(p18));
        }
        if (i == 19) {
          client.print("&p19=" + String(p19));
        }
        if (i == 20) {
          client.print("&p20=" + String(p20));
        }
        if (i == 21) {
          client.print("&p21=" + String(p21));
        }
        if (i == 22) {
          client.print("&p22=" + String(p22));
        }
        if (i == 23) {
          client.print("&p23=" + String(p23));
        }
        if (i == 24) {
          client.print("&p24=" + String(p24));
        }
        if (i == 25) {
          client.print("&p25=" + String(p25));
        }
        if (i == 26) {
          client.print("&p26=" + String(p26));
        }
        if (i == 27) {
          client.print("&p27=" + String(p27));
        }
        if (i == 28) {
          client.print("&p28=" + String(p28));
        }
        if (i == 29) {
          client.print("&p29=" + String(p29));
        }
        if (i == 30) {
          client.print("&p30=" + String(p30));
        }
        if (i == 31) {
          client.print("&p31=" + String(p31));
        }
        if (i == 32) {
          client.print("&p32=" + String(p32));
        }
        if (i == 33) {
          client.print("&p33=" + String(p33));
        }
        if (i == 34) {
          client.print("&p34=" + String(p34));
        }
        if (i == 35) {
          client.print("&p35=" + String(p35));
        }
        if (i == 36) {
          client.print("&p36=" + String(p36));
        }
        if (i == 37) {
          client.print("&p37=" + String(p37));
        }
        if (i == 38) {
          client.print("&p38=" + String(p38));
        }
        if (i == 39) {
          client.print("&p39=" + String(p39));
        }
        if (i == 40) {
          client.print("&p40=" + String(p40));
        }
        if (i == 41) {
          client.print("&p41=" + String(p41));
        }
        if (i == 42) {
          client.print("&p42=" + String(p42));
        }
        if (i == 43) {
          client.print("&p43=" + String(p43));
        }
        if (i == 44) {
          client.print("&p44=" + String(p44));
        }
        if (i == 45) {
          client.print("&p45=" + String(p45));
        }
        if (i == 46) {
          client.print("&p46=" + String(p46));
        }
        if (i == 47) {
          client.print("&p47=" + String(p47));
        }
        if (i == 48) {
          client.print("&p48=" + String(p48));
        }
        if (i == 49) {
          client.print("&p49=" + String(p49));
        }
        if (i == 50) {
          client.print("&p50=" + String(p50));
        }
        if (i == 51) {
          client.print("&p51=" + String(p51));
        }
        if (i == 52) {
          client.print("&p2=" + String(p52));
        }
        if (i == 53) {
          client.print("&p53=" + String(p53));
        }
        if (i == 54) {
          client.print("&p54=" + String(p54));
        }
        if (i == 55) {
          client.print("&55=" + String(p55));
        }
        if (i == 56) {
          client.print("&p56=" + String(p56));
        }
        if (i == 57) {
          client.print("&p57=" + String(p57));
        }
        if (i == 58) {
          client.print("&p58=" + String(p58));
        }
        if (i == 59) {
          client.print("&p59=" + String(p59));
        }
        if (i == 60) {
          client.print("&p60=" + String(p60));
        }
        if (i == 61) {
          client.print("&p61=" + String(p61));
        }
        if (i == 62) {
          client.print("&p62=" + String(p62));
        }
        if (i == 63) {
          client.print("&p63=" + String(p63));
        }
        if (i == 64) {
          client.print("&p64=" + String(p64));
        }
        if (i == 65) {
          client.print("&p65=" + String(p65));
        }
        if (i == 66) {
          client.print("&p66=" + String(p66));
        }
        if (i == 67) {
          client.print("&p67=" + String(p67));
        }
        if (i == 68) {
          client.print("&p68=" + String(p68));
        }
        if (i == 69) {
          client.print("&p69=" + String(p69));
        }
        if (i == 70) {
          client.print("&p70=" + String(p70));
        }
        if (i == 71) {
          client.print("&p71=" + String(p71));
        }
        if (i == 72) {
          client.print("&p72=" + String(p72));
        }
        if (i == 73) {
          client.print("&p73=" + String(p73));
        }
        if (i == 74) {
          client.print("&p74=" + String(p74));
        }
        if (i == 75) {
          client.print("&p75=" + String(p75));
        }
        if (i == 76) {
          client.print("&p76=" + String(p76));
        }
        if (i == 77) {
          client.print("&p77=" + String(p77));
        }
        if (i == 78) {
          client.print("&p78=" + String(p78));
        }
        if (i == 79) {
          client.print("&p79=" + String(p79));
        }
        if (i == 80) {
          client.print("&p80=" + String(p80));
        }
        if (i == 81) {
          client.print("&p81=" + String(p81));
        }
        if (i == 82) {
          client.print("&p82=" + String(p82));
        }
        if (i == 83) {
          client.print("&p83=" + String(p83));
        }
        if (i == 84) {
          client.print("&p84=" + String(p84));
        }
        if (i == 85) {
          client.print("&p85=" + String(p85));
        }
        if (i == 86) {
          client.print("&p86=" + String(p86));
        }
        if (i == 87) {
          client.print("&p87=" + String(p87));
        }
        if (i == 88) {
          client.print("&p88=" + String(p88));
        }
        if (i == 89) {
          client.print("&p89=" + String(p89));
        }
        if (i == 90) {
          client.print("&p90=" + String(p90));
        }
  
      }

Ho implementato un ciclo "for" per cercare di ridurre successivamente tutte quelle righe

Si ma @docdoc nel post #11 ti ha chiaramente detto di non usare 90 variabili e di NON usare oggetti String neppure come funzione che per intendersi è questa:

String(p2)

ovvero dovresti crearti un array di int e gestire il tutto come ti ha suggerito lui, ti ha anche fatto il codice con le inizializzazioni dell'array per i parametri e l'array di char per la stringa da inviare al server.
Come vedi si sta avverando quello che tutti ti abbiamo detto, se usi la classe String vai inevitabilemente a scontrarti con errori legati all'allocazione e deallocazione dimanica in memoria che su Arduino portano a blocchi/errori improvvisi e, all'apparenza, non spiegabili.
Se vuoi che il tuo sistema sia stabile NEL TEMPO e non per una singola prova allora sei obbligato ad eliminare totalmente oggetti e funzioni String con le stringhe classiche del C e relative funzioni per manipolarle (concatenazione, sostituzione, copia, ecc.)

Ho letto la porzione di codice che ha avuto la pazienza, ammirevole, di scrivere, e la ho trovata enormemente rindondante. A parte che, cosa che le é stato detto di evitare, fa uso di String() e che non é quanto le é stato chiesto, ovvero il programma completo da visionare ho pensato che si potrebbe ridurre giusto un filino.
Dato un array di 90 elementi di tipo dei vari pN (o, se sono di tipi diversi, di tipo abbastanza grande da contenerne) si può scrivere una for con quattro righe di codice, che avranno lo stesso comportamento di quella attuale:

client.print ("i primi due caratteri");
client.print (vatiabiledifor);
client.print ('=');
client.print (p[variabiledifor]);

4 righe che NON usano string, e che chiunque conosca le funzioni che utilizza può scrivere.
Mi dispiace che abbia usato cosìbtanto tempo a scrivere tutti gli if credendo forse di non avere tempo per impare. Se si fosse fermato un attimo a leggere nello stesso tempo che ha usato per scrivere il codice avrebbe non solo scritto il codice, ma anche appreso un "trucco" che le sarebbe potuto tornare utile.

Io NON sono arrabbiato con uno che non mi ha fatto nulla. Io vorrei solo riflettere su questo fatto