[ Risolto ] Velocizzare carico pagina web da sd

Salve e grazie a tutti che potranno aiutarmi
esperimento fatto con arduino mega e ethernet shield W5100 con scheda sd
avevo trovato un vecchio topic che dichiarava di aver trovato la soluzione per caricare velocemente le pagine web da sd per evitare il caricamento lento ma non funziona,
di seguito posto lo sketch

......
byte buf[64];
......
if (myFile){
  byte c = 0;
  while (myFile.available()){
    buf[c++] = myFile.read();
    if(c > 63){
      client.write(buf, 64);
      c = 0;
      }
    if(c > 0) client.write(buf, c);
    myFile.close();
    }
  }

mi potete dare qualche dritta
Grazie

Sicuro che i 2 if fossero entrambi dentro il while?
Secondo me il secondo if e il close() vanno fuori dal while.

Controllato svista memorabile
Grazie, posto lo sketch funzionante

myFile = SD.open("luci3.txt");        //trasmette parte di pagina web
if (myFile){
  int c = 0;             
  while (myFile.available()){
    buf[c++] = myFile.read();
    if(c > 63){
      client.write(buf,64);
      c = 0;
      }
    }
  if(c > 0) client.write(buf,c);
  myFile.close();
  }

Mi sapete spiegare perchè se lo metto nel void loop() funziona,
ma visto che lo devo fare girare 6 volte, usando un void di richiamo non funziona

Ho visto l'altra discussione, ma non saprei. A prima vista non vedo cose strane.
Con dei Serial.print controlla se entra nell'if e nel while.

Scusate la mia ignoranza in html,
c'è un motivo particolare perchè l'array buf è di 64??
grazie

p.s.
le pagine ora si caricano che è una meraviglia

provato e riprovato, un - client.write - da - void - esterno dal - void loop() - non lo esegue
all'interno del void loop()
carica --- cose strane (solo per me)

Hai capito dov'è che si ferma?
Entra nella funzione web?
Entra nell'if?
Entra nel while?
Se capisci fin dove arriva si circoscrive il problema

il programma entra in void web()
legge tutto, infatti in Serial.print si legge tutto il file,
ma se client.write si trova nel void web() non riesce a inviare,
se sposti tutto all'interno del void loop() funziona

darbac:
c'è un motivo particolare perchè l'array buf è di 64??

Infatti secondo me la dimensione del buffer è troppo piccola. In questo modo spezzetti l'invio dello stream http in tantissimi pacchetti di piccola dimensione.
Con ESP8266 ad esempio ho fatto alcuni esperimenti e il limite è circa 2/3Kb, con esp32 puoi arrivare anche a 4Kb o più.
Io proverei ad aumentare tipo 512 o 1024 byte e vedi come va.
P.S. Le variabili usate (buf[] e c) mettile tutte in locale

P.S.S. prova a mettere lo sketch completo

di seguito ti metto lo sketch completo del web server.
c'è un modo per eliminare tutti gli if(), ho provato con switch, ma non riesco a farlo girare.
per il resto è client.write() che messo fuori dal loop() non mi manda nulla

codice inviato come file perchè il forum mi dice massimo 9000 caratteri
l'ultimo pezzo di tabella delle temperature è da ultimare, funziona tutto bene,
tranne che per quel void web(), e se si possono eliminare un po' di if
grazie

MASTER_TEMP.ino (18.2 KB)

La funzione web che hai definito non ha senso perché l'oggetto client che hai dichiarato globale non sa a chi deve inviare quei dati.
Se guardi nel loop() infatti, trovi l'istruzione EthernetClient client = server.available(); In questo caso client è locale ed è l'oggetto ritornato dal server quando ad esempio un browser si collega.

Per farla funzionare come vorresti tu puoi fare ad esempio cosi:

void web(EthernetClient* client ){
  myFile = SD.open("visione.txt");
  if (myFile){
    int c = 0;             
    while (myFile.available()){
      buf[c++] = myFile.read();
      if(c > 63){
        client->write(buf,64);
        c = 0;
        Serial.write(buf,64);
        }
      }
    if(c > 0) client->write(buf,c);
    myFile.close();
    }
  }

E quindi quando ti serve la chiami passandogli il puntatore a client, ma quello locale ovviamente (quello globale è inutile, puoi eliminarlo)

web(&client);

Per il resto, perdona la franchezza, ma il problema non sono solo la sbrodolata di if consecutivi, ma l'approccio con cui elabori le richieste del client e prepari la risposta.
Prima di mettersi li a buttar giù righe e righe di codice, è bene sempre fermarsi un secondo e pensare "qual'è il modo più efficiente per fare questa cosa?".

Se la richiesta del client la fai in modo più strutturato ad esempio tipo /?type=TM&number=1&sub=A ti basta fare UNA sola funzione di parsing che ti ricava tutti i parametri necessari dalla stringa passata con il browser (ci sono alcuni esempi proprio qui sul forum sul come).

Stessa cosa per la risposta caricata dalla SD: ripeti sempre lo stesso codice cambiando solo il nome del file.
La funzione web() potrebbe prendere come parametro anche il nome del file ad esempio. La scrivi 1 volta sola, la usi ogni volta che ti serve.

cotestatnt:
E quindi quando ti serve la chiami passandogli il puntatore a client, ma quello locale ovviamente (quello globale è inutile, puoi eliminarlo)

Si, oppure, più semplicemente, può lasciare quello globale ed evitare di ridefinirlo ossia togliendo "EthernetClient" da riga 65 del suo codice:

...
    TR[com] = 0;
    }
  
  //EthernetClient client = server.available();
  client = server.available(); // Uso la variabile globale
  if (client) {   
...

Per il resto, concordo con tutte le considerazioni di cotestatnt.

docdoc:
Si, oppure, più semplicemente, può lasciare quello globale ed evitare di ridefinirlo ossia togliendo "EthernetClient"

In questo modo però sarebbe più difficoltosa la gestione della connessione da parte di più client (ammesso che sia una cosa che interessa)

Grazie per la dritta del void web(); funziona alla perfezione
per gli if() ci sto lavorando ma la vedo dura,
problemino la pagina visione temperature fa un refresch per tenere aggiornata la temperatura
qundi se entra un secondo client e il primo rimane connesso, gli sballa sempre la pagina.
sarebbe abbastanza se si può, che l'ultimo client abbia la priorità sul precedente o lo scolleghi
Grazie mille arrivare ai vostri livelli sarebbe un sogno

darbac:
problemino la pagina visione temperature fa un refresh

Approfondisci come fare delle chiamate AJAX direttamente da una pagina web (Javascript) e dimentica il refresh temporizzato della pagina, è roba preistorica e non porta mai a risultati decenti.

A maggior ragione considerando che le pagine html le puoi caricare da SD e che quindi te le puoi sviluppare con tutta calma anche con un piccolo webserver che gira sul PC volendo e trasferirle quando sei soddisfatto.

Se cerchi tipo "arduino ajax webserver" viene fuori molta roba, questo ad esempio mi sembra un buon tutorial dettagliato (e spiega un minimo anche la parte HTML, che poi è il nocciolo della questione).

Salve e grazie a chi mi dato spunto per capire e migliorare lo sketch
trovata anche la soluzione per eliminare tutti gli - if() -
per comando da web, di seguito la modifica
grazie

   if (readString.indexOf("SCH") > 0){
      byte da = (readString.indexOf("SCH")+3);
      byte a = (readString.indexOf("COM"));
      String scheda = readString.substring(da, a);
      tx[1] = scheda.toInt();
      da = (readString.indexOf("COM")+3);
      a = (readString.indexOf("$"));
      String comando = readString.substring(da, a);
      tx[2] = comando.toInt();
    }

Con questo troncone di sketch, estraggo delle sottostringhe, le converto in numero e le assegno all'array di trasmissione

Un paio di note...
indexOf() quando non trova nulla restituisce -1 e non 0.

Hai scelto una sintassi "strana", mi spiego:
quando fai una richiesta GET al tuo webserver il modo "corretto" per passare dei parametri è usare la sintassi
?param1=value1&param2=value2&param3=value3 etc etc

Ad esempio se nella tua pagina web inserisci una form HTML ovvero la classica finestra di inserimento dati + invio, il browser comporrà la query usando quella sintassi.
Ad esempio questo pezzettino di HTML, quando clicchi sul pulsante "submit" farà in automatico una chiamata all'indirizzo
/sendContact?fname=John&lname=Doe
compilando in automatico le coppie di parametro/valore da passare.

<html>
<body>

<h2>HTML Forms</h2>

<form action="/sendContact">
  <label for="fname">First name:</label>

  <input type="text" id="fname" name="fname" value="John">

  <label for="lname">Last name:</label>

  <input type="text" id="lname" name="lname" value="Doe">


  <input type="submit" value="Submit">
</form> 

<p>If you click the "Submit" button, the form-data will be sent to a page called "/sendContact".</p>

</body>
</html>

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.