Go Down

Topic: AQUABOUN'S /// GESTION D'AQUARIUM RECIFAL (Read 15203 times) previous topic - next topic

djbouns

avec ce que j'ai vu sur le net,
client.print("location.href='/'");
devrait marché :(

djbouns

J'ai trouvé ca qui marche, que je trouve assez simple mais il faut attendre plusieurs seconde entre chaque click sinon sa marche pas :(
une idée pourquoi si long ?

client.println("<button onClick=location.href='./?LED=ON'>ON</button>");

et dans le loop

cadena.concat(c);  

int posicion=cadena.indexOf("LED=");        
          if(cadena.substring(posicion)=="LED=ON")    
         {
test = test +1;                          
         }


Que me conseille tu ? cette méthode est bonne et peut être adapter a tout mes nombreux bouton ou faut il que je creuse sur ton code, il ne me manque que le retour a la page après le clic ... et vu ton niveau, je pencherais pour ton code :)


J-M-L

#32
Oct 11, 2017, 10:32 am Last Edit: Oct 11, 2017, 10:36 am by J-M-L
la librairie n'est pas top pour plusieurs requêtes trop rapide en provenance du même navigateur et l'ESP-01 a ses propres contraintes aussi de ce côté là - un shield ethernet ou une carte wifi de plus haut niveau est bien utile si vous voulez plus de robustesse .

Sinon vous retombez dans l'usage de la classe String... pas bon...

avec
Code: [Select]
client.println("<button onClick=location.href='./?LED=ON'>ON</button>");

l'URL va être capturée par mon code du post #6 quand la loop appelle la fonction:
envoyerPageWeb(WiFiEspClient &client, const char * urlRequest)

la variable urlRequest vaudra alors "/?LED=ON" vous pouvez regardez dans mon autre tuto comment on analyse proprement cette requête si vous voulez de la dynamité (LED qui peut être autre chose et ON aussi) ou si vous avez peu de boutons faire comme dans mon code ci dessus en comparant la requête reçue avec "/" ou "/admin" --> tester avec "/?LED=ON"

si vous retournez toujours la même page web après modif éventuellement de certains param lors de la requête  il suffit de modifier un peu la fonction pour d'abord tester l'URL et faire les modifs puis ensuite balancer la page

Code: [Select]
void envoyerPageWeb(WiFiEspClient &client, const char * urlRequest)
{
  static int reqCount = 0;

  // ************* ICI TESTER L'URL RECUE POUR DECIDER QUOI FAIRE *************
  if (!strcmp(urlRequest, "/")) {  // page de base
     reqCount = 0; // par exemple une requête sur la home page remet à 0 le compteur du serveur
  } else if (!strcmp(urlRequest, "/?LED=ON")) {  // requête d'un bouton
     reqCount++; // par exemple on modifie une variable utilisée plus tard dans la page
  } else if (!strcmp(urlRequest, "/?LED=OFF")) {  // requête d'un bouton
     reqCount--;  // par exemple on modifie une variable utilisée plus tard dans la page
  }

  // **********************************************************************

  // puis on génère la page qui va bien
  // On envoie un en tête de réponse HTTP standard  client.print(
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: text/html\r\n"
    "Connection: close\r\n" // la connexion sera close par le navigateur à la fin de la réponse
    "\r\n");                // une ligne vide marque la fin du header HTTP
  client.print(F("<!DOCTYPE HTML>\r\n"));
  client.print(F("<html><head>\r\n"));
  client.print(F("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n"));
  client.print(F("<title>AQUABOUN</title>\r\n"));

    // On envoie la page web
  client.print(F("<style type=\"text/css\">\r\n"));
  client.print(F("body {background-color: #00979c}\r\n")); // couleur arduino
  client.print(F("</style></head>\r\n"));
  client.print(F("<body>\r\n"));
  client.print(F("<h1>Salut djbouns !</h1>\r\n"));
  client.print(F("Nb de demandes ="));
  client.print(reqCount);
  client.print(F("<br>\r\n"));
  client.print(F("Valeur lue sur A0: "));
  client.print(analogRead(0));
  client.print(F("<br>\r\n"));
  client.print(F("</body>"));
  client.print(F("</html>\r\n"));

  // un peu d'attente pour que le module ESP ait fini de tout envoyer
  delay(10);
}


pour tester même s'il n'y a pas de boutons dans la page générée, vous pouvez taper directement dans la barre d'adresse du navigateur  http://<ip>/?LED=ON ou http://<ip>/?LED=OFF et vous allez voir la variable s'incrémenter ou se décrémenter

OK ?
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

MicroQuettas

#33
Oct 11, 2017, 03:47 pm Last Edit: Oct 11, 2017, 05:00 pm by MicroQuettas
Bonjour à toutes et à tous,

Ayant un peu galéré sur le sujet avant d'arriver à quelque chose de cohérent et qui marche, je me permets d'intervenir sur la façon de faire générer une requête à un navigateur...

Regardons cela sur un exemple, une page et la requête que le navigateur génère quand on clique sur un bouton après avoir rempli les champs de saisie. Le code complet de la page est en PJ.

La requête est une GET, la plus employée, qui ressemble à cela, aux variations de navigateur près:

Code: [Select]

GET /BTS10.htm?T80=admin&T81=pass&N01=01 HTTP/1.1
Host: 192.168.1.236
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.236/BTS10.htm?T80=&T81=&N01=01
Connection: keep-alive
Upgrade-Insecure-Requests: 1


Cette requête demande une ressource (URI) dont l'identification complète est :
192.168.1.236/BTS10.htm?T80=admin&T81=pass&N01=01
Il y a 3 parties:
  • un site "192.168.1.236", ici identifié par une adresse IP. Le navigateur la place dans la ligne "Host".
  • une page "BTS10.htm" située à la racine du site,
  • des informations passées au serveur pour qu'il génère la page: "T80=admin&T81=pass&N01=01" (*) Cette partie est aussi appelée "tail" par les anglosaxons. Je garderai le mot anglais...


Comment mettre ce qu'il faut dans une page html pour que le navigateur génère une requête bien propre ?

Regardons cela sur l'exemple :

Le site : sauf si on veut en changer, il n'y a rien à mettre. Par défaut, le navigateur reste sur le site où il est,

La page : elle se précise dans la balise ouvrante <form action='BTS10.htm'> qui ouvre un formulaire. S'il n'y en a qu'une appelez la "index.htm" comme tout le monde,

Les infos passées à la page sont générées par chacune des commandes sur le formulaire : boutons, entrées, sélecteurs, etc. Cette partie peut être vide, par ex. pour la requête initiale sur un serveur,
Ici, deux boîtes de texte et un bouton.
Pour chaque commande, le même format au retour: "name=value"

Voyons comment décrire cela en html pour la première boîte de texte :
<input name='T80' type='text' size='30'  maxlength='20' style='font-size: 12pt'>

Un champ "name", mais pas de "value", car le champ s'affiche vide avant la saisie. Si j'avais voulu mettre une valeur par défaut, j'aurais ajouté : value='defaut', écrit ici sans l'accent.
Il s'agit d'une saisie de texte type='text' et le reste sont des formatages.

A l'exécution, j'ai tapé "admin" que l'on retrouve au retour dans le champ "T80=admin".

La boîte de texte T2 est identique, sauf qu'il s'agit d'un mot de passe :
<input name='T81' type='password' size='30'  maxlength='20' style='font-size: 12pt'>
Ayant saisi "pass", elle retourne T81=pass.

Maintenant, le bouton :
<button name='N01' type='submit' value ='01'><p class='Bt1'>Valider</p></button>

Les champs importants sont le "name" et la "value" que l'on retrouve au retour dans la requête : "N01=01".

Comment cela marche t'il ?

Rien de plus simple : lorsqu'on clique un bouton, le navigateur collecte toutes les "values" des boîtes d'entrée et termine par celle du bouton cliqué (il ne peut y en avoir qu'un).
Il met le tout à la file, les entrées étant séparées par "&" et l'on obtient :
"T80=admin&T81=pass&N01=01" placé, dans une requête GET, après la page séparé par un "?", sur la première ligne, après le GET et un blanc, soit :
/BTS10.htm?T80=admin&T81=pass&N01=01

Le "/" indique le page demandée est sur la racine du site.

Le traitement de la requête reçue comprend deux étapes :
  • isoler la page et le "tail" dans la requête,
  • dans le "tail", extraire les informations nécessaires.


Il y a plein de bibliothèques et de routines (dont celles de J-M-L) qui font cela, mais il faut d'abord avoir le bon code html pour générer une requête correcte.

Dans votre cas, vous utilisez le "onClick=selection.href="...". C'est du Javascript. Ca a marché dans votre exemple, mais cela n'est pas fait pour cela. Réservez le pour changer de site, pas pour passer des infos à votre serveur.

Voila, j'espère que cela va vous aider. Le fichier joint est le code html de la page exemple. Vous pouvez l'ouvrir avec votre navigateur. En cliquant sur un bouton, le navigateur générera une erreur, mais il affichera la page et le "tail"  de sa requête (en tout cas Firefox le fait).

Je vous invite à bidouiller le code de la page, en regardant en direct sur votre navigateur ce qu'il fait. C'est super pour mettre au point une page.

Pour le détail du html, format, commandes, accents, couleurs, etc, un site un peu ancien mais très complet, avec plein d'exemples, même si la navigation y est un peu touffue:
http://www.info.univ-angers.fr/~gh/selfhtml_fr/

Bon courage, ce n'est pas simple au début, mais une fois que l'on a quelque chose qui marche, cela fait plaisir. On perfectionne ensuite au fur et à mesure.

Enfin, il y a de multiples façons de faire, à chacun la sienne...

A+

MicroQuettas


(*) Les puristes auraient utilisé une requête POST pour ce cas. Ils ont raison, mais c'est pour un exemple de la requête GET.

djbouns

#34
Oct 12, 2017, 12:18 am Last Edit: Oct 12, 2017, 09:27 am by djbouns
l'ESP-01 a ses propres contraintes aussi de ce côté là
une carte wifi de plus haut niveau est bien utile si vous voulez plus de robustesse .
Plusieurs fois ou vous aborder ce sujet/problème.
Que me conseiller vous ? (il doivent etre utiliser via tx/rx)

esp12 ?

esp32 ?

Je ne vais pas rester bloquer sur ce projet a cause d'un composant ... j'ai déjà assez avec le code ... :)

djbouns

#35
Oct 12, 2017, 12:33 am Last Edit: Oct 12, 2017, 12:36 am by djbouns
OK ?
J'ai bien compris le principe dont cela doit fonctionner mais je doit continuer a travailler un code a partir de : envoyerPageWeb(WiFiEspClient &client, const char * urlRequest)
ou pas.
Il semblerais que ce ne soit pas adapter a mon utilisation au dire de MicroQuettas.

Pourtant, cela fonctionne mise a par se problème de vitesse avec le bouton qui n'est pas pris en compte.
Sinon, pour contrer cela, il est peut être possible de faire un champs pour saisir directement la valeur voulu et valider, se qui ne ferait qu'une demande ... ??? qu'en penser vous ?


J'arrive vraiment a un problème de compréhension a ce niveau  a cause d'une chose assez simple.
Jusque a présent, mis a par les thermes d'écriture qui m'était inconnu, la saisie des ligne de commande avait une logique et un sens.
Ce qui me bloque dans les exemple ect ... c'est ce genre de chose :
httpLine[indexMessage++] =  c;
(c == '\n' && currentLineIsBlank)
char * ptrGET, *ptrEspace;
Qui n'ons ni queue ni tète pour moi et ce n'est pas faute de lire et relire, de faire des recherche avec l'IDE avec la fonction trouvée pour essayer de comprendre a quoi se rapporte chaque élément.
Je passe ~3h le matin et ~4h la nuit depuis plusieurs jour a vous lire et lire des dizaines de post sur le net.
Ma motivation est vraiment importante mais j'arrive a un point ou je me demande si le poisson n'est pas trop gros et je suis conscient du temps que vous prenez.


djbouns

Bon courage, ce n'est pas simple au début, mais une fois que l'on a quelque chose qui marche, cela fait plaisir. On perfectionne ensuite au fur et à mesure.


Bonjour MicroQuettas

Merci pour ton explication détaillé.
Je vais prendre le temps de tester cette page afin de comprendre les conséquence de chaque Click.




J-M-L

#37
Oct 12, 2017, 10:26 am Last Edit: Oct 12, 2017, 10:38 am by J-M-L
Pour comprendre cette ligne httpLine[indexMessage++] =  c; il faut la décomposer

httpLine est un tableau de caractères d'une certaine taille dans lequel on va ranger les uns après les autres les caractères que l'on reçoit sur la ligne Série.  dans notre cas la variable c. Pour les mettre les uns après les autres il nous faut une variable qui va parcourir le tableau et se souvenir de l'endroit où l'on doit ranger le prochain caractère. J'utilise la variable indexMessage pour cela.

donc pour mettre c dans le tableau à la position indexMessage, on écrirait simplement

httpLine[indexMessage] =  c;
ensuite il faut se souvenir qu'on a rempli cette case et donc passer à la case d'après. Donc après avoir stocké c au bon endroit on devrait faire un un truc du genre indexMessage = indexMessage + 1;

il existe dans le langage C une instruction ++ qui incrémente (ajoute 1 unité) directement une variable.

donc au lieu de faire indexMessage = indexMessage + 1;, je pourrais écrire indexMessage++; et mon code serait

httpLine[indexMessage] =  c;
indexMessage++;

Il faut savoir que l'on peut mettre le ++ avant ou après le nom de la variable et ça ne fait pas tout à fait la même chose:

a = 3;
b = a++; // ici on met a dans b et ensuite on augmente a de 1, donc b vaut 3 et a vaut 4 après exécution
b = ++a; // ici on augmente a de 1 d'abord puis met a dans b ensuite, donc b vaut 4 et a vaut 4 après exécution

En tenant compte de cette information on voit que l'on peut faire donc tout d'un seul coup:

httpLine[indexMessage++] = c;

ça veut dire mettre c dans le tableau httpLine à la position indexMessage, puis ensuite augmenter de 1 indexMessage

OK ?


if (c == '\n' && currentLineIsBlank) ça c'est plutôt simple. l'opérateur && c'est le ET logique (si condition1 est vraie ET condition2 est vraie alors...). Ici on regarde donc si j'ai reçu un retour chariot et que la ligne précédente était vide (une variable que l'on maintient pendant qu'on reçoit les caratères) alors faire quelque chose --> la raison de cela est expliquée dans mon tuto, une requête HTTP se termine par une ligne vide, c'est comme cela que l'on repère la fin de la demande du navigateur.

OK?


char * ptrGET, *ptrEspace; ça déclare simplement 2 pointeurs sur des caractères;
l'objectif du code qui suit est d'extraire du tableau la partie qui concerne l'URL reçue. c'est ce code

Code: [Select]
if (ptrGET = strstr(httpLine, "GET")) {
   // c'est la requête GET, la ligne continent "GET /URL HTTP/1.1", on extrait l'URL
   ptrEspace = strstr(ptrGET + 4, " ");
   *ptrEspace = '\0';
   strncpy(urlRequest, ptrGET + 4, maxURL);
   urlRequest[maxURL] = '\0'; // par précaution si URL trop longue
}



En supposant que la ligne contient bien "GET /ADMIN HTTP/1.1" on veut alors extraire /ADMIN pour s'en souvenir et le passer ensuite à la fonction d'affichage de la page web.

voici ce que fait ce code





est clair ?


Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

djbouns

#38
Oct 12, 2017, 10:42 am Last Edit: Oct 12, 2017, 10:42 am by djbouns
dire oui serait un mensonge.

J'ai compris le principe de ce qui est fait/demander mais c'est l'écriture (surtout si il y a des "raccourci") que je ne fait pas correspondre a l'action.

Il faut que j'y arrive, je vais y passer du temps, je revient vers vous si question précise.

sachab

Bonjour

Sujet très intéressant.

Djbouns, j'ai déjà fait ton arduino balling, et il fonctionne impec, jusqu'à présent aucun bug.
Est il possible d'avoir le code du nouveau projet?

Perso je partirai sur un esp32 (26 Digital IO et 12 Analog input pins)

Si tu veux un esp12, j'en ai 1, je peux te l'envoyer, c'est Kdo!


A+

Sacha

djbouns

Bonsoir Sachab,

J'ai utilisé mes pompe de dosage pour le balling plusieurs année sans aucun problème, juste de l'usure et de la corrosion sur les partie "moteur" (a 5€ l'unité, rien d'anormal)

J'espère que ce nouveau projet seras aussi stable et efficace.

J'ai commander un esp32. (3€ plus chere qu'un esp12) je pense le recevoir mardi.

Pour le code il est partager ici dans le but de le faire évoluer et aboutir.
Il n'as volontairement pas été mis pour le moment sur recifal france.

bricoleau

Bonjour

Sujet très intéressant.

Djbouns, j'ai déjà fait ton arduino balling, et il fonctionne impec, jusqu'à présent aucun bug.
Merci  :)

Voir la troisième ligne du code.

djbouns

:) et oui  :smiley-wink:  



Je ne suis pas du genre a m'approprier le travaille des autres :)

arfff ... déjà 3 ans et demi ... :smiley-eek-blue:



djbouns

Bon ...

A part me remémorer de vieux souvenir :) 
 ....

J'ai (enfin) réussi a adapter le code de JML (celui des variables pour led) a ma connexion WIFI.
J'ai donc la page qui s'affiche correctement.
Je me lance dans l'expérience pour remplacer la page d'origine par la mienne avec les bouton correspondant.

1er remarque :
Les boutons sont en "location.href=" tout comme le code que j'ai reussi a faire fonctionner, par contre, le click rapide sur le bouton réagi beaucoup mieux que dans mon code (mais c'est pas encore sa) mais de façon aléatoire, les Click rapide finisse par générer une page "la page ne peut s'afficher". a voir si avec l'esp32 cela seras réduit.

2eme remarque :
Ma page étant assez grande, je doit descendre avec ma roulette de souris pour faire défiler les fonctions.
Des que je clik sur un bouton, je re bascule en haut de la page, se qui oblige a redescendre ... ect ...

Si besoin je mettrait le code, en cours de test, il est pas propre la :)

djbouns

Problème rencontré a l'adaptation avec mon code pour modifier les variables correspondant aux haure de lever et coucher soleil (pwm led)

Je déclarais ces variable en hhmmss exemple 123000 pour 12h30.
il me parraisait compliquer de pouvoir  modifier cette variable du fait quelle ne peut etre traiter en centiemme puisque il s'agit d'heure.

j'ai donc testé la chose suivante
Code: [Select]
long Hlever = 12;
int Mlever = 34;
long LEVER = ((Hlever*10000)+(Mlever*100)); // heure debut levé

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
Serial.print(Hlever);
Serial.print("H");
Serial.println(Mlever);

}

void loop() {
  // put your main code here, to run repeatedly:


long LEVER = ((Hlever*10000)+(Mlever*100));
Serial.println(LEVER);

Mlever = Mlever +10;
delay (2000);
Serial.print(Hlever);
Serial.print("H");
Serial.println(Mlever);
Mlever = Mlever+10;
delay (2000);
Serial.print(Hlever);
Serial.print("H");
Serial.println(Mlever);
Mlever = Mlever+10;
delay (2000);
if (Mlever>=60){
Mlever = Mlever-60;
Hlever = Hlever+1; 
}
Serial.print(Hlever);
Serial.print("H");
Serial.println(Mlever);
LEVER = ((Hlever*10000)+(Mlever*100));
Serial.println(LEVER);
delay (20000);



}


Y avait il une solution plus simple qui ne me faisait pas modifier mon code d'origine ?


Go Up