Exemple d'usage du shield Ethernet pour faire un serveur interactif

J'ai un projet à peu près similaire, mon but est d'afficher les données de capteurs sur une page HTML dasn un réseau, cependant je stocke mon HTM et le CSS dans la carte SD et je ne trouve pas comment afficher les variables de mes capteurs sur mon site internet, quelqu'un sait-il comment s'y prendre?

vous pouvez utiliser AJAX - cf mon début de tuto Techniques "avancées" de serveur web sur ESP8266. Il faudra juste lire sur la carte SD au lieu du fichier SPIFFS

Bonjour, ce serait intéressant de convertir ce tuto pour utilisation avec esp8266. (bon moi j'essaie mais je n'y arrive pas, ce qui n'est pas étonnant vu mon niveau)

luckymaxou: Bonjour, ce serait intéressant de convertir ce tuto pour utilisation avec esp8266. (bon moi j'essaie mais je n'y arrive pas, ce qui n'est pas étonnant vu mon niveau)

J'en ai un qui est un peu plus poussé pour l'ESP -> cf Techniques "avancées" de serveur web sur ESP8266 vu que la carte est plus puissante qu'un UNO.... faut pas s'en priver

merci J-M-L
juste entre parenthèse, (pour ce qui est des techniques avancées, j’ai testé à 2 reprises et je n’ai même pas réussi à passer la première étape (l’installation du .jar…: à l’extraction du zip que je reçois de Github il ne contient pas de .jar, alors je n’imagine même pas la suite et j’ai renoncé…)
mais ce petit tuto du Shield me semblait à ma portée, un du même niveau au niveau client serveur esp serait génial, c’est juste une suggestion, il n’y a pas beaucoup de tutos destinés aux vrais débutants…

luckymaxou:
Ce petit tuto du Shield me semblait à ma portée, un du même niveau au niveau client serveur esp serait génial, c’est juste une suggestion, il n’y a pas beaucoup de tutos destinés aux vrais débutants…

ben c’est pas très compliqué, il suffit d’adapter la séquence d’initialisation dans le setup pour le WiFi au lieu d’ethernet (il y a des exemples) et ensuite c’est quasiment pareil on remplace la classe EthernetClient par WiFiClient

la LED doit être connectée en pin D1 du Wemos

#include <ESP8266WiFi.h>

const char* ssid = "VOTRE_SSID";  // <===== A REMPLIR AVEC VOTRE NOM RESEAU WiFi
const char* password = "VOTRE_MDP"; // <===== A REMPLIR AVEC VOTRE MOT DE PASSE DU RESEAU WiFi

const unsigned int SERVER_PORT = 80;
WiFiServer webServer(SERVER_PORT);

const byte MaxCommand = 30;
char urlCommand[MaxCommand + 1]; // +1 for the trailing '\0'

// ****************************************************************
// This is for our URL Parser. We are expecting an URL in the form
// of http://domain.com/x=v1,y=v2,z=v3
// x, y and z would be the labels of Interests and v1, v2, v3
// will be valued extracted by the parser
// ****************************************************************
const char * labelsOfInterest[] = {"LED", "V", "W"};
const size_t maxLabelsOfInterest = sizeof(labelsOfInterest) / sizeof(char*);
long V = 0, W = 0;
const byte LEDPin = D1;

void parseCommand()
{
  char * item;
  boolean labelFound;
  long int labelValue;
  int labelIndex;

  item = strtok(urlCommand, "=");

  while (item) {
    labelFound = false;
    for (size_t i = 0; i < maxLabelsOfInterest; ++i) {
      if (!strcmp(labelsOfInterest[i], item)) {
        item = strtok (NULL, ",");
        if (item != NULL) {
          labelFound = true;
          labelIndex = i;
          // then parse the value
          // we expect integers
          labelValue = atol(item);
          break; // ends the for loop as we found a label
        } // end if we had a value for the label
      } // end string compare
    } // end for

    // ****************************************************************
    // THIS IS WHERE YOU PERFORM YOUR ACTIONS FOR EACH VARIABLE FOUND
    // ****************************************************************

    if (labelFound) {
      switch (labelIndex) {
        case 0: // LED
          digitalWrite(LEDPin, (byte) labelValue);
          break;
        case 1: // V
          V += labelValue;
          break;
        case 2: // W
          W += labelValue;
          break;
      }
      // ****************************************************************
    } else {
      item = strtok (NULL, ","); // skip this label value, not recognized
    }

    item = strtok (NULL, "="); // got to next one - will modify urlCommand
  }
}



void sendHTTPResponse(WiFiClient& client)
{
  // send a standard http response header
  client.println(F("HTTP/1.1 200 OK"));
  client.println(F("Content-Type: text/html"));
  client.println(F("Connection: close"));  // the connection will be closed after completion of the response
  // client.println(F("Refresh: 30"));  // refresh the page automatically every 30 sec
  client.println();
  client.println(F("<!DOCTYPE HTML>"));

  // ****************************************************************
  // THIS IS WHERE YOU BUILD YOUR HTML PAGE
  // ****************************************************************

  client.println(F("<html><head><style>body {text-align:center;}</style></head>")); // body will be centered
  client.println(F("<body bgcolor='#00979C'>")); // page backgroud color

  // V Value
  client.print(F("V=")); client.print(V); client.println(F("
"));
  client.print(F("<button onclick=\"location.href='/V=1'\" type='button'>V +1</button>"));
  client.print(F("<button onclick=\"location.href='/V=-1'\" type='button'>V -1</button>"));
  client.println(F("


"));

  // W Value
  client.print(F("W=")); client.print(W); client.println(F("
"));
  client.print(F("<button onclick=\"location.href='/W=5'\" type='button'>W +5</button>"));
  client.print(F("<button onclick=\"location.href='/W=-5'\" type='button'>W -5</button>"));
  client.println(F("


"));

  // LED button
  if (digitalRead(LEDPin) == LOW)
    client.print(F("<button onclick=\"location.href='/LED=1'\" type='button'>LED ON</button>"));
  else
    client.print(F("<button onclick=\"location.href='/LED=0'\" type='button'>LED OFF</button>"));

  // Reset button
  client.println(F("


"));
  client.print(F("<button onclick=\"location.href='/LED=0,V="));
  client.print(-V);
  client.print(F(",W="));
  client.print(-W);
  client.print(F("'\" type='button'>RESET</button>"));

  client.println(F("</center></body></html>"));
}



void handleCommand(WiFiClient& client)
{
  // the command is in urlCommand
  if (strlen(urlCommand) != 0) parseCommand();
  sendHTTPResponse(client);
}


void handleClient()
{
  boolean urlCommandFound = false;
  char httpHeader[MaxCommand + 1];
  byte httpHeaderIndex = 0;
  httpHeader[0] = '\0';
  urlCommand[0] = '\0';

  WiFiClient client = webServer.available();     // listen for incoming clients

  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // Serial.print(c); // if you want to see the HTTP request
        if (!urlCommandFound) {
          httpHeader[httpHeaderIndex++] = c;
          httpHeader[httpHeaderIndex] = '\0';
          if (httpHeaderIndex > MaxCommand - 1) httpHeaderIndex = MaxCommand - 1;
        }

        if (c == '\n' && currentLineIsBlank) {  // an http request ends with a blank line
          handleCommand(client);
          delay(5); // give the web browser time to receive the data
          client.stop(); // close the connection:
          break;
        }

        if (c == '\n') {
          currentLineIsBlank = true; // starting a new line
          if (!strncmp("GET / ", httpHeader, 5)) {
            strcpy(urlCommand, (httpHeader + 5)); // get rid of the "GET / "
            char * firstSpacePtr = strchr(urlCommand, ' ');
            if (firstSpacePtr) *firstSpacePtr = '\0'; // get rid of the " HTTP / 1.1 etc
            urlCommandFound = true;
          } else {
            httpHeaderIndex = 0;
            httpHeader[0] = '\0';
          }
        } else if (c != '\r') {
          currentLineIsBlank = false; // new character on the current line, ignore '\r'
        }
      }
    }
  }
}

void printServerAddress()
{
  Serial.print(F("connect to your ESP8266 with http://"));
  Serial.print(WiFi.localIP());
  if (SERVER_PORT != 80) { // 80 is the default port so not needed in the URL
    Serial.print(F(":"));
    Serial.println(SERVER_PORT);
  }
}


void setup()
{
  pinMode(LEDPin, OUTPUT);
  digitalWrite(LEDPin, LOW);

  Serial.begin(115200);
  while (!Serial);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print(F("Connecting to "));
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(F("."));
  }
  Serial.println();
  Serial.println(F("WiFi connected"));

  // Start the server
  webServer.begin();
  printServerAddress();
}

void loop()
{
  handleClient();
  // you can do other stuff here but don't take too long
}

(testé sur un Wemos(Lolin) R2)

Merci beaucoup J-M-L effectivement ça marche sur mon nodemcu esp12, maintenant je vais essayer de le modifier et l'arranger à ma sauce...

avec plaisir!

Bonjour, merci encore pour ce super tuto... Quand vous dites qu'on peut rajouter des lignes dans le loop "sans être trop long", on peut aller jusqu'où ? j'ai l'intention d'interroger un serveur npt toutes les minutes et d'ajouter un programme avec quelques conditions basé sur la "Machine à état".

luckymaxou: Quand vous dites qu'on peut rajouter des lignes dans le loop "sans être trop long", on peut aller jusqu'où ?

Si vous ne revenez pas vérifier s'il y a un client en attente "assez souvent", vous risquez de rater des requêtes HTTP. Donc ne mettez pas un delay d'une heure après :)

ok, merci J-M-L :)

de rien - amusez vous bien !

Bonjour, ce tuto marche, merci encore J-M-L ! j'aimerais juste comprendre un point : à quoi correspond le F dans le client.println ? mon débogueur dit que c'est une macro, où est-elle ? que fait elle ? merci LuckyMaxou

Pour le F(“xxx”) ça conservera la chaîne en mémoire flash au lieu de la SRAM

Cf en bas de la page sur PROGMEM

ok merci

Bonjour JML

suite à mes questions précédentes au sujet du post " techniques avancées..."

je suis revenu tester ton code du #25 de ce post "shield ethernet..."

mon problème est le suivant:

ton code est fonctionnel. j'y ai ajouté l'affichage de deux sondes DS1821

et j'ai besoin que l'affichage soit rafraichi périodiquement pour que les températures soient justes.

j'ai donc libéré la ligne client.println(F("Refresh: 1")); en mettant la periode à 1 seconde .

l'affichage des températures est bien évolutif .

et si je demande par exemple V+1, le V s'incrémente bien de 1

le problème est que le V continu à s'incrémenter toutes les secondes.

dans le doute j'ai repris ton code du #25 que j'ai testé brut, simplement en libérant la ligne de rafraichissement ...et le problème est le meme.

y a t'il une parade ou suis je obligé de reprendre mes tentatives d'adaptation de ton code de "techniques avancées"?

salut

oui c’est le challenge de demander un “Refresh” simple, la dernière URL utilisée pour la page est soumise à nouveau et comme elle comprend des paramètres, ils sont à nouveaux interprétés.

on peut utiliser la forme longue de mémoire ce serait un truc du genre (à mettre dans le header, pas dans le corps)

<META HTTP-EQUIV="Refresh" CONTENT="1;URL=http://192.168.1.29">

(mettre dans l’URL le point d’entrée de votre carte, sans param - ne pas utiliser pour une redirection)

hello JML
merci de ta réponse
voici ce que j’ai mis, mais le compilo n’accepte pas, j’ai une erreur
"unterminated argument list invoking macro “F”

je pense qu’il n’aime pas les guillements intermédiaires dans la ligne

client.println(F("<html><head><style>body {text-align:center;}</style>")); // body will be centered
  client.println(F("<META HTTP-EQUIV="Refresh" CONTENT="1;URL=http://192.168.11.29">"));
  client.println(F("</head>"));

nota: j’ai changé les chiffres de l’adresse

Tout à fait !

il faut escaper les guillemets dans la chaîne sinon le compilateur ne retrouve pas ses petits

client.println(F([color=green]"[/color]<META HTTP-EQUIV=[color=red]\"[/color]Refresh[color=red]\"[/color] CONTENT=[color=red]\"[/color]1;URL=http://192.168.11.29[color=red]\"[/color]>[color=green]"[/color]));

c'est ok, un grand MERCI :)

je vais pouvoir continuer ma bricole je reverrai plus tard avec ton code de "technique avancée" lorsque tu l'auras étoffé. pour l'instant, j'ai bien rajouté les boutons onclick mais pour l'instant, la page ne fait que lire que que l'arduino lui donne, mais ne renvoie pas une demande ( de +1 ou +5p ar exemple. mais là, je peux attendre sereinement, tu m'as bien débloqué.

Merci encore :)