IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Le navigateur aux commandes de l'Arduino - Partie 1 : télécommande et télémétrie,
Un tutoriel d'Hervé Troadec

Le , par naute

0PARTAGES

23  0 
Bonjour à tous ,

j'ai le plaisir de vous présenter mon tutoriel :

Le navigateur aux commandes de l'Arduino

dans l'espoir qu'il puisse vous être utile.

Amicalement,
naute

Retrouvez les meilleurs cours et tutoriels Système embarqué

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de f-leb
Responsable Arduino et Systèmes Embarqués https://www.developpez.com
Le 01/02/2020 à 18:35
Bravo pour ce tutoriel Enfin un Arduino connecté, le sujet est porteur et très bien traité.

J'attends la deuxième partie avec impatience, je vais encore apprendre plein de choses...
5  0 
Avatar de jpbbricole
Membre émérite https://www.developpez.com
Le 01/02/2020 à 19:49
Bonsoir
Citation Envoyé par f-leb Voir le message
Bravo pour ce tutoriel Enfin un Arduino connecté, le sujet est porteur et très bien traité.
Je plussoie (10 fois!) f-leb.
Magnifique!. Je dois garder ce tuto sous le coude, j'ai découvert une chose qui m'occupe beaucoup et qui est, pour moi, un "bijou" pour développer, le M5stack Grey (~40$)et, en plus, il a tout ce qu'il faut pour appliquer ce tuto.
Donc, l'étude avant tout

Bonne soirée
Cordialement
jpbbricole
5  0 
Avatar de Jay M
Expert confirmé https://www.developpez.com
Le 02/02/2020 à 13:12
beau boulot et bel effort qui sera bien utile aux débutants - bravo !

---

Quelques petits commentaires qui se veulent constructifs

* la page HTML 5 minimum recommandée ressemble plus à cela:
Code HTML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html> 
  
<html> 
  
  <head> 
    <title>contenu pour la barre de titre du navigateur</title> 
  </head> 
  
  <body> 
  </body> 
  
</html>
(c'est une bonne pratique que d'encapsuler la balise de titre (<title>) dans la balise d'en-tête (<head>) qui délimite des informations qui ne seront pas affichées directement dans la zone de rendu du navigateur. L'exemple ici est le titre de la page mais on y trouvera aussi un lien vers la feuille de style, une description et des mots clés, etc.)

* Vous faites un très bon point sur l'usage de la macro F() pour ne pas surcharger la SRAM

Si je peux me permettre, on peut aller un cran plus loin pour apporter un peu de simplicité pour insérer une page HTML dans le code en utilisant le concept C++ de raw string literals.

ça permet de ne pas s'encombrer des séquences d'échappement pour les guillemets et donc de copier directement de l'HTML depuis un éditeur et ça aère le code de votre programme car on n'y voit pas toute la page web, juste une référence à la variable qui contient le contenu. (ça permet aussi de ne pas répéter plusieurs fois le code de l'en-tête par exemple, on le range dans une variable et on imprime cela, si vous devez le modifier il suffit alors de le modifier qu'à un seul endroit).

Ça fonctionne comme cela: dans l'IDE vous créez un nouvel onglet, que vous appelez par exemple codeHTML.h et vous mettez dedans:
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// C++ raw string literals cf http://en.cppreference.com/w/cpp/language/string_literal 
// USE PROGMEM with Program Space Utilities http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html 
 
const char webRoot[] PROGMEM = R"--8<--8<--(HTTP/1.1 200 OK 
Content-Type: text/html 
Connection: close 
 
<!DOCTYPE html> 
<html lang="fr"> 
<meta charset="utf-8" /> 
<title>Ma première page</title> 
<body> 
  <div> 
    <h3>Informations sur la page</h3> 
    <p>Cette page HTML ne contient qu’un peu de texte, avec un minimum de mise en forme pour l’exemple. Elle fait appel aux fonctionnalités de base d'un navigateur, à savoir afficher du texte et établir un hyperlien. Sa syntaxe satisfait aux exigences du W3C.</p> 
    <p>Le <a href="https://fr.wikipedia.org/wiki/World_Wide_Web_Consortium">W3C</a> (<i>World Wide Web Consortium</i>), est l’organisme ayant en charge la promotion et la standardisation du Web.</p> 
  </div> 
</body> 
</html> 
)--8<--8<--";
Je déclare donc une constante nommée webRoot de type tableau de caractère qui est stocké en mémoire flash (grace au PROGMEM) et notez le R (pour raw) juste après le signe = et avant le texte HTML. C'est qui introduit cette notion de raw littéral. Il y a usage d'une séquence d'identification de début et fin de texte (ici j'ai mis --8<--8<--).

ensuite dans le .ino du programme principal il suffit d'inclure codeHTML.h et on accède aux données comme pour une cString stockée en mémoire programme, par exemple

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "codeHTML.h" 
 
void setup() { 
  Serial.begin(115200); 
  uint16_t nbBytes = strlen_P(webRoot); // la taille en octets du buffer 
  Serial.print(F("Voici les ")); 
  Serial.print(nbBytes); 
  Serial.println(F(" octets de la page web")); 
  Serial.println(F("-----------")); 
  Serial.println((const __FlashStringHelper *) webRoot);  // on transforme le type pour que la fonction print s'y retrouve 
} 
 
void loop() {}


* Enfin personnellement (surtout sur un UNO) je recommanderais de ne pas utiliser la classe String pour bâtir caractère par caractère la requête mais d'utiliser simplement une cString (un tableau de char) que vous remplissez. ça va libérer plein de mémoire programme (utile pour votre code HTML) et évite aussi des risques de fragmentation mémoire et de crash intempestifs. au lieu de indexOf() pour voir si un mot clé est reconnu, on utilisera alors la fonction strstr()

Tout cela n'est pas obligatoire et votre tuto est très bien tel qu'il est, mais j'espère que cela peut aider. Merci encore pour ce super boulot.
5  0 
Avatar de Vincent PETIT
Modérateur https://www.developpez.com
Le 01/02/2020 à 22:26

Super tuto, très intéressant !
Bravo et merci pour la communauté

J'attends aussi la partie 2 avec impatience

A+
Vincent
3  0 
Avatar de naute
Rédacteur https://www.developpez.com
Le 02/02/2020 à 11:56
Bonjour .

à vous trois, vos encouragements me vont droit au .

Par contre :
Citation Envoyé par f-leb Voir le message
je vais encore apprendre plein de choses...
Il conviendrait peut-être rester dans les limites du vraisemblable . Et comme ma phrase pourrait avoir un double sens, je précise "non pas parce-que tu ne serais pas capable d'apprendre quelque-chose, mais plutôt parce-que je ne suis pas convaincu de pouvoir t'enseigner quoi que ce soit" .

La deuxième partie avance, mais sa rédaction me demande plus de temps que prévu. Je fais au mieux (enfin j'essaye ).

Bon dimanche,
naute
3  0 
Avatar de naute
Rédacteur https://www.developpez.com
Le 03/02/2020 à 15:30
Bonjour Jay M ,

et merci pour vos commentaires.

Citation Envoyé par Jay M Voir le message

la page HTML 5 minimum recommandée ressemble plus à cela...
Sur la page du W3Schools concernant la balise <head>, on trouve la mention suivante :


Differences Between HTML 4.01 and HTML5
In HTML 4.01 the <head> element is required.
In HTML5, the <head> element can be omitted. The following code will validate as HTML5:
Donc, à priori, mon code minimal est correct. La balise <head> n'est toutefois pas interdite, mais son usage semble laissé à l'appréciation de la clientèle. Cela dit, je l'utilise d'une manière générale, mais dans le cas présent, étant donné le peu d'entrées se trouvant dans l'entête, j'ai décidé de m'en passer. Ce n'est pas un oubli.

Citation Envoyé par Jay M Voir le message
Si je peux me permettre
Bien sûr, on est là pour ça .

Citation Envoyé par Jay M Voir le message

on peut aller un cran plus loin pour apporter un peu de simplicité pour insérer une page HTML dans le code en utilisant le concept C++ de raw string literals.
C'est un peu une question de point de vue : techniquement, l'utilisation de "l'échappement" est très simple (à défaut d'être élégant dans notre cas, je le reconnais volontiers) et a le mérite d'être largement répandu dans les différents langages de programmation. Il ne faut pas oublier que les utilisateurs d'Arduino viennent d'horizon différents et ne manipulent pas forcément le C/C++ avec allégresse et aisance . Je préfère donc, dans la mesure du possible, m'en tenir à la manipulation des éléments courants du langage Arduino sur lesquels on ne peut pas faire l'impasse. De même, stocker le texte dans un autre fichier est intéressant, mais il me semble préférable dans un tutoriel destiné plutôt au débutants, de rester centré sur le sujet. J'ai déjà assez tendance à m'en éloigner involontairement pour ne pas en rajouter volontairement. La remarque est cependant tout à fait justifiée.

Citation Envoyé par Jay M Voir le message
ça permet aussi de ne pas répéter plusieurs fois le code de l'en-tête par exemple
Je traite ce problème, mais d'une façon différente, dans la deuxième partie (à venir), car là, c'est pertinent. Ici, le code de l'entête n'est utilisé qu'une fois, donc le stocker différemment dans le but de le réutiliser n'a techniquement pas d'intérêt.

Merci pour le mode d'emploi de raw string literals. Winjerome m'avait déjà suggéré de l'utiliser, mais j'ai préféré m'en tenir à "l'échappement" pour les raisons évoquées plus haut.

Je suis également d'accord sur vos remarques concernant la classe String, mais comme je l'ai dit plus haut, je préfère m'en tenir le plus possible au langage Arduino, c'est-à-dire aux éléments qui sont détaillés dans la référence officielle de ce langage, à laquelle tous les utilisateurs ont accès depuis l'EDI. Cette classe est facile à utiliser et fournit globalement toutes les méthodes de gestion de chaîne dont on peut avoir besoin. Il est vrai qu'elle peut poser problème dans certains cas, mais ça ne m'est jamais arrivé. Il faut dire que la gestion du texte avec Arduino n'est pas mon utilisation standard de la plateforme.

Merci encore pour votre intervention ,
amicalement,
naute
2  0 
Avatar de Jay M
Expert confirmé https://www.developpez.com
Le 03/02/2020 à 17:22
Bonsoir

bon point sur le code minimal en HTML5 effectivement.

bien sûr l'échappement est une technique standard, tout comme les raw string literals qui font partie du langage - mais je comprends votre objectif de simplicité. (notez qu'on n'est pas obligé de le mettre dans un autre fichier c'est juste pour simplifier le code principal)

Pour les chaînes de caractère la référence officielle mentionne qu'on peut les représenter du texte de deux façons. Une fois que l'on a une cString on peut utiliser donc toute la richesse de la bibliothèque standard du langage C ou C++. (stdlib.h et string.h )

Personnellement j'évite comme la peste la classe String car le jour où vous avez un souci de stabilité (pour des applications qui doivent tourner longtemps) pour débugger c'est difficile.

Pour des petits programmes qui ont vocation à tourner quelques minutes ou pour lesquels l'usage de la classe se résume à une seule String allouée dynamiquement en variable locale (et détruite à la fin de la fonction) alors c'est jouable.

Cela se fait aussi au prix quand même d'un usage plus conséquent de la mémoire car la classe String est gourmande. Pour s'en convaincre, si vous compilez
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
String message = "Hello World";

void setup() {
  Serial.begin(115200);
  Serial.println(message);
  if (message.indexOf("World")) Serial.println(F("'World' PRESENT"));
}

void loop() {}
Le croquis utilise 3366 octets et Les variables globales utilisent 216 octets

et si vous compilez le programme suivant qui fait la même chose
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
char message[] = "Hello World";

void setup() {
  Serial.begin(115200);
  Serial.println(message);
  if (strstr(message,"World")) Serial.println(F("'World' PRESENT"));
}

void loop() {}
Le croquis utilise 1906 octets et Les variables globales utilisent 206 octets

--> on a gagné 10 octets de RAM et 1&#8239;460 de mémoire programme...

Quand on joue avec du HTML sur nos petits Arduinos, on peut stocker quand même pas mal de contenu web dans ces 1460 octets.

mais bon - je conviens que ces considérations sont un peu éloignées de votre objectif premier de découverte de la communication http. éventuellement à ajouter dans un autre chapitre 'pour aller plus loin'
2  0 
Avatar de Jay M
Expert confirmé https://www.developpez.com
Le 31/10/2020 à 0:29
Citation Envoyé par Baptou88 Voir le message
Bonjour,
j'arrive bien à réceptionner l'info du slider sur ma carte ( -> GET /VALUE=65 HTTP/1.1 ) mais je souhaiterai pouvoir isoler la valeur numérique, Comment faire?
Si vous utilisez le code du tutorial, votre requête GET est dans la String réception donc vous pouvez utiliser toutes les méthodes de cette classe

Vous pouvez vérifier comme dans le tuto si la chaîne commence par "GET" et se termine par "HTTP/1.1" et si oui trouver la position de "VALUE=" Et si cette position existe, utiliser toInt() sur la sous chaîne (substring(from)) qui commence après cette position+Les 6 caractères de "VALUE="
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
 reception.trim();
      if ((reception.startsWith("GET /")) && (reception.endsWith(" HTTP/1.1")))
      {
        int pos = reception.indexOf("VALUE=");
        if (pos != -1) {
          // il y a bien une VALUE
          // a écrire. Utiliser reception.subString(à remplir).toInt();
        } else {
          // pas trouvé
        }
...
2  0 
Avatar de Jay M
Expert confirmé https://www.developpez.com
Le 16/02/2021 à 0:46
Citation Envoyé par Beginner. Voir le message

Si j'ai bien compris ici le PC et la carte Arduino sont connectés au réseau local d'une box, c'est bien ça ?

C'est-à-dire qu'il ne s'agit pas d'une commande à distance (via Internet) de la carte Arduino, c'est bien ça ?
(Répondu aussi dans l’autre fil, mais pour mémoire)

A moins d’utiliser l’arduino pour créer un réseau local auquel d’autres éléments viennent se joindre, vous rejoignez toujours un réseau local. Les règles d’accès à un Noeud particulier du réseau depuis internet dépendent de la façon dont l’administrateur réseau a configuré son système. Généralement on ne donnera pas un accès direct à un ordinateur au sein du réseau standard, c’est plutôt réservé aux ordinateurs serveurs de la DMZ.

Votre question touche donc plus la gestion d’un réseau que la carte Arduino en elle même.
2  0 
Avatar de f-leb
Responsable Arduino et Systèmes Embarqués https://www.developpez.com
Le 16/02/2021 à 18:17
Bonjour,

Citation Envoyé par Beginner. Voir le message
Oui merci. En fait dans ce fil je voulais parler du cas particulier de ce tuto dans lequel il me semble que la carte Arduino n'est pas commandée à distance via internet mais plutôt elle est commandée par le navigateur d'un appareil connecté au même réseau local que la carte Arduino...

Je voulais juste avoir une confirmation pour savoir si j'avais bien compris...
L'Arduino du tuto est configuré en serveur, et avec les box domestiques il n'y a rien à faire de particulier pour que les clients du réseau local puissent accéder au serveur.
Mais le serveur ici n'a rien de sécurisé, configurer la box pour donner les accès depuis l'extérieur ne serait pas très prudent
2  0