Contrôler une LED par le web (IDE 1.0)

Bonjour à tous,

J'ai un nouveau petit problème.
Je cherche à comprendre comment faire communiquer mon arduino avec une page web (en utilisant un serveur externe).
J'ai trouvé un excellent tutoriel http://blog.weeboo.net/tutoriel-arduino-ethernet-shield-controler-led-depuis-une-page-web/
J'ai réussi à faire fonctionner ce système avec l'IDE 023.
J'essaie maintenant de le transposer pour qu'il fonctionne avec l'IDE 1.01, j'ai presque réussi, mais il me reste une erreur à la compilation que je n'arrive pas à solutionner.
ici : Udp.readPacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
J'ai l'erreur suivante :
LED_PHP.cpp: In function 'void loop()':
LED_PHP:89: error: 'class EthernetUDP' has no member named 'readPacket'

Voici mon code :

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 49);

unsigned int localPort = 8888;      // local port to listen on

byte remoteIp[4];        // holds received packet's originating IP
unsigned int remotePort; // holds received packet's originating port

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  Serial.begin(9600);
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if(packetSize)
  
// la partie qui suit et qui est commentée vient de l'exemple "UDPSendReceiveString.ino" de la librairie Ethernet
/*  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply, to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}
*/
 {
    packetSize = packetSize - 8;      // subtract the 8 byte header
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
 
    memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE);
 
    // read the packet into packetBufffer and get the senders IP addr and port number
    Udp.readPacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
    Serial.println("Contents:");
    Serial.println(packetBuffer);
 
    analogWrite(9, atoi(packetBuffer)); //utiliser la valeur reçu pour allumer la led
  }
  delay(2);
}

Merci pour votre aide.

bonjour, je crois que maintenant la fonction que tu cherche est Udp.parsePacket(packetBuffer,UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort);
ou alors c'est Udo.read tout cours que sais je :s je vois pas à quoi sert cette ligne, si c'est juste pour lire ce qu'il y a dans le buffeur c'est déjà ce que fait Udp.read.. donc à quoi est sensé te servir cette ligne?

Merci skizoh,

J'essaierai cela ce soir.

En fait pour mon projet de domotique : http://arduino.cc/forum/index.php/topic,80422.360.html
d'un point de vue des fonctions, il me reste à traiter la partie "échanges de données" avec un site web.
Il s'agit d'afficher sur un site web, des données issues de l'arduino (état de sorties, d'entrées, températures, ...), mais aussi de saisir via le site des informations telles que les plages horaires de fonctionnement, de pouvoir modifier l'état de certaines sorties, ...
Le site sera hébergé sur un petit serveur, type serveur apache.

Or, c'est un domaine qui m'est inconnu.
Donc, j'essaye d'avancer pas à pas en cherchant des exemples qui fonctionnent pour essayer de comprendre ou au moins d'arriver à identifier des fonctions qui me permettront de petit à petit, à faire ce que je veux.
Là j'ai trouvé un exemple (et un tutoriel) de commande d'une sortie par un petit bout de php, je ne comprends pas dans le détail, mais j'espère en manipulant un "truc" qui fonctionne, arriver à comprendre des choses.

@+

pas de problème, alors moi si je doit te conseiller un support pour faire passer des info extérieur au pc sur le web ce sera le python, tu peut tres facilement mettre en place un petit serveur web et dans le même programme recevoir et emmetre par liaison série ou encore écrire dans un fichier, autant te dir tout ce qu'il te faut quoi ! le transfert de donné en UDP est bien choisie c'est simple et peut soumis au problème de perte de connexion avec l'hote, bref va geter un coup d'oeuille à ca:

web: http://fr.wikibooks.org/wiki/Apprendre_à_programmer_avec_Python/Applications_web

python web =) :3.11.3 Documentation

J'ai jeté un rapide coup d'oeil, sur les liens, je regarderai plus en détail.

Je pensai à une solution php mysql, bien que ne connaissant pas grand chose de ces langages, pour avoir une base de données dans laquelle seraient stockées toutes les données : plages horaires, relevés de températures ...

Est ce que Python permet cela?
Comment fonctionne Python, en se substituant au html ? Ou en générant du html ?
Mes questions sont probablement idiotes ! Mais j'essaye d'y voir plus clair.

@+

Salut,

Bon déja par rapport aux fonctions UDP de la librairie ethernet :
Elle ont TOUTES était modifié (enfin une trés trés grandes partie), les sketchs, tutoriels, etc ... conçu avec arduino 0023 (ou antérieur) ne compilerons pas sur arduino 1.0.
La transition 0023 -> 1.0 a imposé un nombre considérable de modifications ... surtout dans la librairie ethernet.
Faire tout les changements dans un programme <=0023 pour qu'il compile sur 1.0 demanderai pas mal de temps.

De plus pourquoi vouloir absolument utiliser le protocole UDP ?
En UDP il n'y as pas de vérification de la bonne réception des données et de leurs intégrités !

A pars si c'est vraiment impératif d'utiliser de l'UDP tu ferais mieux de rester sur une solution simple basé sur TCP.
Les fonctions de base de la librairie ethernet fonctionnent avec TCP et n'ont jamais était modifié (contrairement aux fonctions UDP).

Brisebee:
Je pensai à une solution php mysql, bien que ne connaissant pas grand chose de ces langages, pour avoir une base de données dans laquelle seraient stockées toutes les données : plages horaires, relevés de températures ...

Le langage PHP est trés puissant (et relativement simple), couplé avec une base de données MySQL il n'y aura aucun probléme pour concevoir un systéme de relevé de température, de plages horaire, etc ...

Par contre avant de ce lancer tête baisser dans le code, il faudra réfléchir à la structure de la base de données, et se documenter sur le langage PHP et SQL :wink:
Pour PHP / mySQL : http://www.siteduzero.com/tutoriel-3-14668-concevez-votre-site-web-avec-php-et-mysql.html

Brisebee:
Est ce que Python permet cela?
Comment fonctionne Python, en se substituant au html ? Ou en générant du html ?

Python est un langage de programmation parmi d'autre, il permet de faire beaucoup de chose de manière simple et rapide.
Par contre python ne se substitut à rien et ne génère rien !

Contrairement à PHP, python n'est pas un langage conçu pour faire des sites web (à l'origine).
Il est possible d'en faire via divers modules mais ce n'est pas sont but premier.
Si tu souhaite que python génère du code html il faudra lui donner les instructions pour (de même en PHP) !

skywodd:
De plus pourquoi vouloir absolument utiliser le protocole UDP ?
En UDP il n'y as pas de vérification de la bonne réception des données et de leurs intégrités !

Je ne cherche pas particulièrement à utiliser UDP
C'est uniquement parce que j'avais trouvé un tuto sympa et complet avec un exemple qui fonctionne avec l'IDE 023
Je me suis donc dit que si j'avais un ensemble fonctionnel, je pourrai le modifier pour l'adapter à mon besoin, mais apparemment ce n'est pas si simple que cela, il va donc falloir que je trouve un autre moyen !

Merci pour les explications concernant les langages.

Brisebee:
Je ne cherche pas particulièrement à utiliser UDP
C'est uniquement parce que j'avais trouvé un tuto sympa et complet avec un exemple qui fonctionne avec l'IDE 023
Je me suis donc dit que si j'avais un ensemble fonctionnel, je pourrai le modifier pour l'adapter à mon besoin, mais apparemment ce n'est pas si simple que cela, il va donc falloir que je trouve un autre moyen !

Tu as aussi beaucoup de tutoriel utilisant TCP :wink:
Exemple : http://www.instructables.com/id/Arduino-Web-LED/ (compatible arduino 0023 et 1.0)

Merci skywodd

Dans le tuto que tu me proposes le site est "généré" par l'arduino, il me semblait que c'était très différent d'une configuration dans laquelle le site est hébergé sur un serveur(même local), mais je me trompe peut-être ?

Dans tous les cas, je vais étudier ce tuto, je finirai peut-être par mieux comprendre comment cela fonctionne.

Il y a aussi le site bien connu et très bien fait de X. Hinault avec le tuto qui montre comment commander 7 LEDs,

mais je n'ai pas regardé de trop près pensant que cette solution etait éloignée de la solution qui m'interessait.

@+

Brisebee:
Dans le tuto que tu me proposes le site est "généré" par l'arduino, il me semblait que c'était très différent d'une configuration dans laquelle le site est hébergé sur un serveur(même local), mais je me trompe peut-être ?

Quel boulet j'avais oublié ce point ...
Oui la page web et hébergé sur l'arduino, pas sur un serveur, grosse nuance.

Ce que je fait personnellement c'est souvent des choses à base de socket PHP : PHP: fsockopen - Manual
J'avais fait une tentative de "gestionnaire arduino" à distance mais j'ai rencontré des problémes et j'ai finit par laissé tomber ...
[Commande à distance] Ethernet Firmata, PHP et Jquery | Skyduino - Le DIY à la française
(ça peut toujours donnée quelques pistes)

Yop bribri,
Un exemple presque similaire en tcp, j'ai essayer de faire au plus court et sans superflus pour mieux comprendre.

code html
Comme je sais que tu auras besoin de formulaires j'ai repris l'exemple du site du zero comme ça tu pourras t'y référer pour plus d'explication sur ceux ci.
http://www.siteduzero.com/tutoriel-3-13596-les-formulaires.html#ss_part_4
!

<form method="post" action="traitement.php">

ici ce sera différent comme la requête ce fera via javascript et non directement depuis la page, les attributs méthode et action ce situe côté javascript

"formRequestAjax.html"

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>FormRequestAjax</title>

    <script src="jquery.min.js"></script>
    <script src="webAjax.js"></script>
    

</head>
<body>
 <h3>formulaire Ajax</h3>
 <div id="log"></div>
 


     <form id="myform">
        <p>
            <label for="pseudo">Votre pseudo :</label>
            <input type="text" name="pseudo" id="pseudo" placeholder="Ex : Zozor" size="30" maxlength="10" />
        </p>
        <p>
           Cochez les aliments que vous aimez manger :

           <input type="checkbox" name="frites" id="frites" /> <label for="frites">Frites</label>

           <input type="checkbox" name="steak" id="steak" /> <label for="steak">Steak hache</label>

           <input type="checkbox" name="epinards" id="epinards" /> <label for="epinards">Epinards</label>

           <input type="checkbox" name="huitres" id="huitres" /> <label for="huitres">Huitres</label>
        </p>
        <p>
           <label for="pays">Dans quel pays habitez-vous ?</label>

           <select name="pays" id="pays">
               <option value="france">France</option>
               <option value="espagne">Espagne</option>
               <option value="italie">Italie</option>
               <option value="royaume-uni">Royaume-Uni</option>
               <option value="canada">Canada</option>
               <option value="etats-unis">États-Unis</option>
               <option value="chine">Chine</option>
               <option value="japon">Japon</option>
           </select>
        </p>
    </form>
    <div><button id="bouton" onclick="send()">on</button></div>
    <!-- onclick="send()" //sur clic boutton appel de la fonction javascript send()  -->
    


    <div id="retour"></div>
    
</body>
</html>

pour l'inclusion de la lib

<script src="jquery.min.js"></script>

tu trouveras le fichier ici
https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js

code javascript "webAjax.js"

function send() //fonction qui sera appelé depuis la page html voir -> onclick="send()"
{
  // requête post vers socket.php avec les différentes valeurs du formulaire trouvee grace a la fonction $(id)
  jQuery.post("socket.php", { pseudo: $('pseudo').value, frites: $('frites').checked, pays: $('pays').value }, 
   function(data) //data contiendra la ou les données en retour de la requête
   {
	 $("retour").innerHTML = data; // on integre dans la balise portant l'id "retour" les data de retour
   });
}


function $(id)
{
  return document.getElementById(id); // fonction '

! on peux utiliser le caractère spécial $ (c'est le seul) comme nom , ça permet d'avoir un nom de fonction court et simple pour des appels fréquent, tu remarqueras que la lib jquery l'utilise également dans ses exemples pour remplacer "jQuery.".
Donc comme moi je l'utilise déjà pour autre chose j’appelle "jQuery." directement comme pour "jQuery.post()" aux lieu de "$.post()" sinon il y aurait conflit.

Pour plus d'information su la requête
http://api.jquery.com/jQuery.post/

"socket.php"

<?php

$msg = "";
$buffer = null;

$msg = file_get_contents("php://input"); // on ne reprend que les données utiles et non l'intégralité de la requête 
$host="192.168.1.109";
$port=1080;

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); //création du socket
socket_connect($socket, $host, $port); //connection du socket
socket_write($socket,$msg,strlen($msg)); //envoie des données POST

do
{
  if(isset($buffer)) // si buffer contien des donnees
    echo $buffer; // reponse à la requête javascript
}
while(@socket_recv($socket,$buffer,32,0) != 0); // on attend la reponse (=! 0) sur le socket

socket_close($socket); //fermeture du socket
?>

Le socket attend quelque chose en retour dans la boucle, risque de bloquer si rien en retour mais c'est juste pour tester avec un minimum de code pour l'instant.

code arduino, fonctionne sous 1.01

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {  0x90, 0xA2, 0xDA, 0x00, 0x6D, 0x86 }; // a remplacer
byte ip[] = { 192,168,1,109 }; // a remplacer

EthernetServer server(1080); // 1080 a remplacer si différent
byte nb = 0;

void setup() 
{

  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  server.begin();

}


void loop() 
{
  EthernetClient client = server.available();
  
  if (client) 
  {
    nb++;
    if (client.connected()) 
    {
      while (client.available()) 
      {
        char c = client.read();
        Serial.write(c); //on affiche dans le monitor les caractère reçu

        if(!client.available())
        {

          client.write("j'ai bien reçu la requete "); //réponse avec write
          client.print(nb, DEC); // réponse avec print (nb = nombre de requêtes)
          delay(1);
          
          client.stop();
        }
      }
    }
  }
}

recherche l'element html par son 'id'
}


! on peux utiliser le caractère spécial $ (c'est le seul) comme nom , ça permet d'avoir un nom de fonction court et simple pour des appels fréquent, tu remarqueras que la lib jquery l'utilise également dans ses exemples pour remplacer "jQuery.".
Donc comme moi je l'utilise déjà pour autre chose j’appelle "jQuery." directement comme pour "jQuery.post()" aux lieu de "$.post()" sinon il y aurait conflit. 

Pour plus d'information su la requête
http://api.jquery.com/jQuery.post/

"socket.php"

§DISCOURSE_HOISTED_CODE_4§


Le socket attend quelque chose en retour dans la boucle, risque de bloquer si rien en retour mais c'est juste pour tester avec un minimum de code pour l'instant.

code arduino, fonctionne sous 1.01

§DISCOURSE_HOISTED_CODE_5§

Mille merci Osaka,

Je vais voir tout cela en soirée.
Il va probablement me falloir pas mal de temps pour arriver à ingérer tout cela !
Et le site du zéro sera souvent sollicité.

Avec tout le travail que tu as fait, ce serait sûrement intéressant de faire un (ou des) tuto(s) pour des débutants comme moi qui se posent pleins (trop ?) de questions et qui ne savent pas par quel bout prendre le problème.

@+

Brisebee:
Avec tout le travail que tu as fait, ce serait sûrement intéressant de faire un (ou des) tuto(s) pour des débutants comme moi qui se posent pleins (trop ?) de questions et qui ne savent pas par quel bout prendre le problème.

Le plus gros problème c'est l'utilisation de plusieurs langages différents (html -> JavaScript -> php-> c/c++) , il est difficile de tous les maîtriser donc il faudrait presque un tuto complet sur chacun d'eux si on veut pouvoir aller plus loin que mon exemple qui reste spécifique à ce besoin. :~

Yes !!!!
J'ai réussi à faire fonctionner !
Encore merci.
Je vais pouvoir à partir de maintenant essayer de comprendre comment cela fonctionne.
Enfin pas tout de suite, cars je pars en déplacement à l'étranger la semaine prochaine, et je serai également absent la semaine d'après, je consulterai le forum, mais je n'aurai pas mon arduino avec moi (et de toute façon je n'aurai que très peu de temps).

osaka:

Brisebee:
Avec tout le travail que tu as fait, ce serait sûrement intéressant de faire un (ou des) tuto(s) pour des débutants comme moi qui se posent pleins (trop ?) de questions et qui ne savent pas par quel bout prendre le problème.

Le plus gros problème c'est l'utilisation de plusieurs langages différents (html -> JavaScript -> php-> c/c++) , il est difficile de tous les maîtriser donc il faudrait presque un tuto complet sur chacun d'eux si on veut pouvoir aller plus loin que mon exemple qui reste spécifique à ce besoin. :~

Déjà, un mode opératoire : ce qu'il faut faire pour la mise en oeuvre, ce qui doit se passer et comment interagissent les différents programmes, aiderait certainement ceux qui ne savent pas comment s'y prendre.
Car quelquefois quand on est complèment perdu, il faut reprendre les choses, d'une manière très basique, comme on le ferai pour un enfant (nous sommes tous de grands enfants :wink: ).

@+

@Osaka

Déjà, un mode opératoire : ce qu'il faut faire pour la mise en oeuvre, ce qui doit se passer et comment interagissent les différents programmes, aiderait certainement ceux qui ne savent pas comment s'y prendre.

Moi je suis vraiment intéresser par le mode opératoire même léger, car je cmoprend un peut les principes Apache et arduino, une restitution des codes en fichier zip ca sera excellent.
nous comptons beaucoup sut toi Osaka :*
@+

Dès que j'ai le temps j'essaierais de faire quelque chose pour mieux expliquer les rôles de chacun et leurs interactions pour voire ce qu'il se passe.

bonjour osaka

j'ai essayé ton exemple et j'obtiens les message suivant :
Warning: Unable to open socket in /mnt/130/sdb/d/a/monsite/arduino/webajax/socket.php on line 11
Warning: socket_write() [function.socket-write]: unable to write to socket [32]: Broken pipe in /mnt/130/sdb/d/a/monsite/arduino/webajax/socket.php on line 12

les lignes 11 et 12 :
socket_connect($socket, $host, $port); //connection du socket
socket_write($socket,$msg,strlen($msg)); //envoie des données POST

avec
$host="192.168.0.12";
$port=4920;

l' ip et le port correspondent a ceux déclaré dans le code arduino.

Dans le répertoire il y a les fichiers :
formRequestAjax.html
jquery.min.js
socket.php
webAjax.js

d'ou vient mon erreur??

ah , je précise mon FAI est FREE , n'y a t'il pas un problème de blocage de socket avec FREE ??

Merci de votre aide.

archibal11:
ah , je précise mon FAI est FREE , n'y a t'il pas un problème de blocage de socket avec FREE ??

Tu as bien deviné :grin:, la grande majorité des hébergeur que ce soit mutualisé ou autres n'accepte tout simplement pas la création ou connections de socket. :~

Merci de la réponse rapide.

Donc pour le moment il n'y a pas d'autre moyen..

archibal11:
Donc pour le moment il n'y a pas d'autre moyen..

En local, tu peux te faire ton propre petit hébergement (apache, php, sql, ..) via wamp (windows), lamp (linux) ou mamp (osx).
je suppose que tu es sous windows donc wamp : http://www.wampserver.com/