Go Down

Topic: accélérer serveur web (html/css/js)  (Read 1 time) previous topic - next topic

Jz84100

Je suis content que ça te serves!
on remarque nettement la difference!


bricoleau

Bonjour

J'aime pas rester sur un échec ???

Alors j'ai repris le code que je t'avais indiqué précédemment, j'ai ajouté les deux modifs qui permettent de le faire fonctionner, et je l'ai testé sur une simple arduino ethernet.

Résultat : image jpg de 100ko stockée sur la carte SD de l'arduino, affichée en moins de deux secondes sur le navigateur de mon PC (liaison tout en filaire, pas de wifi).

Voici le code correct
Code: [Select]
#include <SPI.h>
#include <SD.h>
#include <Ethernet.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte ip[] = {192,168,1,4};
char rootFileName[] = "index.htm";
EthernetServer server(80);

Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}

void setup() {
  Serial.begin(9600);
  PgmPrint("Free RAM: ");
  Serial.println(FreeRam());
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  if (!card.init(SPI_FULL_SPEED, 4)) error("card.init failed!");
  if (!volume.init(&card)) error("vol.init failed!");
  PgmPrint("Volume is FAT");
  Serial.println(volume.fatType(),DEC);
  Serial.println();
  if (!root.openRoot(&volume)) error("openRoot failed");
  PgmPrintln("Files found in root:");
  root.ls(LS_DATE | LS_SIZE);
  Serial.println();
  PgmPrintln("Files found in all dirs:");
  root.ls(LS_R);
  Serial.println();
  PgmPrintln("Done");
  Ethernet.begin(mac, ip);
  server.begin();
}
#define BUFSIZ 100

EthernetClient  client;
char buffer[350];//voire plus
uint16_t longueur = 0;

char clientline[BUFSIZ];
void loop()
{
  char *filename;
  int index = 0;
  int image = 0;
  client = server.available();
  if (client) {
    boolean current_line_is_blank = true;
    index = 0;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c != '\n' && c != '\r') {
          clientline[index] = c;
          index++;
          if (index >= BUFSIZ)
            index = BUFSIZ -1;
          continue;
        }
        clientline[index] = 0;
        filename = 0;
        Serial.println(clientline);
        if (strstr(clientline, "GET / ") != 0) {
          filename = rootFileName;
        }
        if (strstr(clientline, "GET /") != 0) {
          if (!filename) filename = clientline + 5;
          (strstr(clientline, " HTTP"))[0] = 0;
          Serial.println(filename);
          if (! file.open(&root, filename, O_READ)) {
            client_println("HTTP/1.1 404 Not Found");
            client_println("Content-Type: text/html");
            client_println();
            client_println("<h2>File Not Found!</h2>");
            break;
          }
          Serial.println("Opened!");
          client_println("HTTP/1.1 200 OK");
          client_print("Content-Type: ");
          if (strstr(filename, ".htm") != 0)
            client_println("text/html");
          else if (strstr(filename, ".css") != 0)
            client_println("text/css");
          else if (strstr(filename, ".png") != 0)
            client_println("image/png");
          else if (strstr(filename, ".jpg") != 0)
            client_println("image/jpeg");
          else if (strstr(filename, ".gif") != 0)
            client_println("image/gif");
          else if (strstr(filename, ".3gp") != 0)
            client_println("video/mpeg");
          else if (strstr(filename, ".pdf") != 0)
            client_println("application/pdf");
          else if (strstr(filename, ".js") != 0)
            client_println("application/x-javascript");
          else if (strstr(filename, ".xml") != 0)
            client_println("application/xml");
          else
            client_println("text");
          client_println();         
          client_send();

          longueur = file.read(buffer, sizeof(buffer));
          while (longueur != 0)
          {
            client_send();
            longueur = file.read(buffer, sizeof(buffer));
          }
          file.close();  //close the file
        }
        else {
          client_println("HTTP/1.1 404 Not Found");
          client_println("Content-Type: text/html");
          client_println();
          client_println("<h2>File Not Found!</h2>");
        }
        break;
      }
    }
    delay(1);
    client.flush();
    client.stop();
  }
}

void client_send() {
  if (longueur != 0) client.write(buffer, longueur);
  longueur = 0;
}

void client_print(char c) {
  buffer[longueur++] = c;
  if (longueur == sizeof(buffer)) client_send();
}

void client_print(char *c) {
  while (*c) client_print(*c++);
}

void client_println() {
  client_print((char)0x0a);
}

void client_println(char c) {
  client_print(c);
  client_println();
}

void client_println(char *c) {
  client_print(c);
  client_println();
}
Tutoriels arduino : http://forum.arduino.cc/index.php?topic=398112.0

Jz84100

Merci c'est génial
Je testerais demain mais si tu dit que ça fonctionne !
C'est top
Par contre je n'y comprends rien....

Ce serveur est top il peut servir de base à tout serveur web sur arduino!
Maintenant j'essaye de faire fonctionner des boutons pour contrôler la led souder sur l'arduino dans un premier temps, mais sans succès...

Jz84100

ouah c'est une fusée c'est top mais j'ai l'impression que une fois sur deux c'est trop rapide et l'arduino ne génère pas la page html il se content de l'envoyé c'est tout
on se retrouve donc souvent dans le navigateur à avoir que le code html....

bricoleau

#19
Jan 26, 2016, 03:06 pm Last Edit: Jan 26, 2016, 03:07 pm by bricoleau
Bonjour

Je ne comprends pas trop ton dernier propos, car les termes utilisés ne sont probablement pas les bons.
Il n'y a pas vraiment de différence entre "générer" une page html et "envoyer" une page html.

Je suppose que tu parles d'un fichier .htm présent sur la carte SD, que l'arduino lit et envoie au client.
Le HTML, c'est un flux texte avec des balises.
Le navigateur traduit ces balises pour afficher la page correctement.
Tu peux lui demander d'afficher le code source de la page, pour visualiser exactement le flux texte reçu de l'arduino. C'est très utile pour mettre au point ton serveur.

Si ce flux est incorrect / tronqué, il va manquer des infos au navigateur pour l'interpréter.
C'est probablement dans ce cas que tu "vois" le html.

Cela peut provenir soit d'un problème de communication entre l'arduino et ton navigateur, soit d'un bug au niveau du code arduino, dans la mécanique de lecture SD / envoi au client.
Là comme ça je ne vois pas trop. Faudrait déjà identifier quel est le bout qui manque.
De mon côté je n'ai pas constaté ce type d'anomalie, mais je n'ai pas fait de test sur un fichier .htm

Dans tous les cas, tu vas avoir du mal à aller significativement plus loin avec un code aussi mal fagoté.
Je serais toi, je remettrais tout ça au propre, avec une structuration des traitements en fonctions.
Cela te permettra aussi de comprendre son fonctionnement, et donc de le maîtriser / modifier.

Commence par faire simple : un serveur web qui renvoie une bête page HTML, jusqu'à comprendre la moindre ligne de code.
Des Serial.print insérés temporairement un peu partout te permettront d'appréhender le fonctionnement.

Idem pour les boutons, car vouloir les ajouter directement sur ce code, sans maîtrise de la programmation, ça va être une galère sans nom qui a peu de chances d'arriver à bon port.
Tutoriels arduino : http://forum.arduino.cc/index.php?topic=398112.0

bricoleau

#20
Jan 26, 2016, 03:20 pm Last Edit: Jan 26, 2016, 03:21 pm by bricoleau
A la limite pour une meilleure lisibilité on peut coder l'envoi du fichier ainsi :
Code: [Select]
          longueur = sizeof(buffer);
          while (longueur == sizeof(buffer))
          {
            longueur = file.read(buffer, sizeof(buffer));
            if (longueur > 0)
            {
              client.write(buffer, longueur);
            }
          }
          file.close();  //close the file
Tutoriels arduino : http://forum.arduino.cc/index.php?topic=398112.0

ptitnitro62000

Petite remarque , ça peu paraitre évident pour certain mais j'ai remarqué:

lorsque que l'on écrit:
Code: [Select]
client.println("Exemple de longue chaine de caractères à envoyer");
la chaine est encapsulé entière.

alors que:
Code: [Select]
client.println(F("Exemple de longue chaine de caractères à envoyer"));
les caractères sont envoyés un par un....

je pense que c'est donc pour cela que l'on est obligé d'envoyé ces lignes suivantes tels quelle sans la macro F():

           client.println("Content-Type: text/html");
           client.println("Connnection: close");;
           client.println();
Arduino uno R3, Arduino Nano V3, Arduino Mega 2560, Arduino DUE, Shield Ethernet + Micro SD, Tiny RTC (DS1307+24c32) , module RTC ( module DS3231 + AT24C32) stater kit de base et plein d'autres trucs sympa ;-)

bricoleau

#22
Jan 27, 2016, 06:53 pm Last Edit: Jan 27, 2016, 06:53 pm by bricoleau
Exact

Les divers types d'appel de print() ou println() s'appuient sur la méthode write(), différente d'un objet à l'autre.
Et write se décline en deux versions write(uint8_t) ou write(const uint8_t *buffer, size_t size)

C'est la version write(uint8_t) qui est utilisée avec une chaîne en flash
Code: [Select]
size_t Print::print(const __FlashStringHelper *ifsh)
{
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}


Mais quand on génère de manière dynamique des pages HTML, par assemblage de chaînes de caractères constantes, l'utilisation de la flash est vite indispensable, sous peine de bouffer toute la RAM.

La solution est de laisser tomber cette bouse de print(), et de gérer soi-même directement les write() :
1) recopie par blocs de la flash vers un buffer temporaire en RAM
2) envoi du buffer au client ethernet par un write(const uint8_t *buffer, size_t size)
Tutoriels arduino : http://forum.arduino.cc/index.php?topic=398112.0

Go Up