Arduino pour la domotique
1 Introduction
1.1 Contenu du document
Le point de départ de ce document a été un projet étudiant de dernière année de l'école d'ingénieurs ISTIA de l'université d'Angers [] : piloter des éléments de la maison (lampe, chauffage, porte de garage, ) avec un mobile, smartphone ou tablette. Ce projet a été proposé par Sébastien Lagrange, enseignant-chercheur de l'ISTIA. Il a été réalisé par six étudiants : Thomas Ballandras, Raphaël Berthomé, Sylvain Blanchon, Richard Carrée, Jérémy Latorre et Ungur Ulu. Le projet a été décliné en trois sous-projets :
- application web mobile avec JSF2 / Primefaces ;
- application web mobile avec HTML5 / Javascript / Windows 8 ;
- application native Android.
Le TP consiste à réaliser les sous-projets 3 et 1 dans cet ordre. Plusieurs documents sont référencés :
- ] : " Introduction aux frameworks JSF2, Primefaces et Primefaces Mobile " disponible à l'URL
[]. Il vous servira pour construire le client web mobile ;
- ] : " Android pour les développeurs J2EE : un modèle asynchrone pour les clients web " disponible à l'URL []. Il vous servira pour construire le client Android ;
- ] : " Introduction à Java EE avec Netbeans 6.8 " disponible à l'URL []. Il vous servira pour construire le serveur ;
- ] : " Introduction au langage Java " disponible à l'URL []. Il vous servira pour construire les serveurs et clients TCP-IP de la couche [DAO] du serveur.
1.2 Le projet Android
L'architecture du projet Android est celle d'une application client / serveur. L'architecture du serveur est la suivante :
Spring / Tomcat 7
Wikipedia donne la définition suivante des Arduinos :
Arduinoest uncircuit impriméen(dont les plans sont publiés en) sur lequel se trouve unqui peut êtreprogrammépour analyser et produire dessignaux électriques, de manière à effectuer des tâches très diverses comme la charge de batteries, la(le contrôle des appareils domestiques - éclairage, chauffage…), le pilotage d'unrobot, etc. C'est une plateforme basée sur une interface entrée/sortie simple et sur un environnement de développement utilisant la technique du Processing/Wiring.
La couche [DAO] est reliée aux arduinos via un réseau. Elle est constituée
- d'un serveur TCP/IP pour enregistrer les Arduinos qui se connectent ;
- d'un client TCP/IP pour envoyer les commandes à exécuter aux Arduinos connectés.
La couche [DAO] peut commander plusieurs Arduinos.
Côté Arduino, on trouve les mêmes composantes mais programmées en langage C :
- un client TCP/IP pour s'enregistrer auprès du serveur d'enregistrement de la couche [DAO] ;
- un serveur TCP/IP pour exécuter les commandes que la couche [DAO] envoie.
Un Arduino peut servir plusieurs clients. Ils sont alors servis séquentiellement.
Les échanges entre la couche [DAO] et un Arduino se font par lignes de texte :
- la couche [DAO] envoie une ligne de texte contenant une commande au format JSON (JavaScript Object Notation) ;
- l'Arduino interprète puis exécute cette commande et renvoie une ligne de texte contenant une réponse également au format JSON.
La couche métier du serveur est exposée au client via un service REST (REpresentational State Transfer) implémenté par le framework Spring MVC.
- la couche [DAO] communique avec le serveur REST. C'est un client REST implémenté par Spring-Android ; la couche [métier] reprend l'interface de la couche [métier] du serveur ;
Les versions actuelles d'Android exigent que les connexions réseau soient faites dans un autre thread que celui qui gère les interfaces visuelles. C'est ce qui explique la présence du bloc [4]. Les méthodes de la couche [métier] sont exécutées au sein d'un thread différent de celui de l'UI (User Interface). Lorsqu'on fait exécuter une méthode de la couche[métier] dans un thread, on peut attendre ou non la réponse de la méthode. Dans le premier cas, synchrone, on bloque l'UI en attendant la réponse de la tâche. Dans le second cas, asynchrone, l'UI reste disponible pour l'utilisateur qui peut lancer d'autres actions. Ici, on a choisi la solution asynchrone pour deux raisons :
- le client Android doit pouvoir commander plusieurs Arduinos simultanément. Par exemple, on veut pouvoir faire clignoter une led placée sur deux Arduinos, en même temps et non pas l'une après l'autre. On ne peut donc attendre la fin de la première tâche pour commencer la seconde ;
- les connexions réseau peuvent être longues ou ne pas aboutir. Pour cette raison, on veut donner à l'utilisateur la possibilité d'interrompre une action qu'il a lancée avec un bouton [Annuler]. Pour cela, l'UI ne doit pas être bloquée.
Les vues [2] sont les interfaces visuelles présentées à l'utilisateur. Sur une tablette, elles ressemblent à ceci :
A partir de cette vue, l'utilisateur lance une action avec le bouton [Exécuter].
Le bloc [3] regroupe les actions exécutées par les vues. La vue ne fait que saisir des données et contrôler leur validité. On part du principe qu'elle ne sait pas à quoi elles vont servir. Elle sait simplement à quelle action elle doit transmettre les données saisies. L'action lancera les tâches asynchrones nécessaires, mettra en forme leurs résultats et rendra à la vue un modèle pour que celle-ci se mette à jour. La vue n'est pas bloquée par l'action, afin de donner à l'utilisateur la possibilité de l'interrompre.
Les activités [1] sont le coeur d'une application Android. Ici on n'en a qu'une et elle ne fait quasiment rien si ce n'est d'assurer les changements de vues. On appellera ce modèle, AVAT (Activité – Vues – Actions – Tâches) et c'est ce modèle que nous allons décrire et illustrer dans ce document. On verra qu'il peut être allégé de la façon suivante :
Dans le modèle AVAT, la vue est complètement ignorante de l'utilisation faite des données qu'elle a saisies. Dans le modèle AVT cidessus (Activité – Vues – Tâches), la logique de l'action est transférée dans la vue. On trouve donc un peu de logique dans la vue. Celle-ci doit organiser les appels des tâches asynchrones elle-même. Cette logique est forcément faible. Si elle était importante, elle serait normalement transférée dans la couche [métier]. Ce modèle AVT est suffisant dans tous les cas. Le modèle AVAT est pour les puristes qui cherchent à limiter la vue à la saisie / affichage de données.
1.3 Le projet Web Mobile
L'architecture du projet web mobile est également celle d'une application client / serveur. Le serveur reste ce qu'il était pour le client Android :
L'architecture du client web mobile est la suivante :
Spring / Tomcat
Sur une tablette, les vues ressemblent à ceci :
Le client web mobile aura les mêmes fonctionnalités que le client Android mais il aura l'avantage de fonctionner sur toutes les tablettes quelque soit l'OS (Android, IOS, Windows 8).
1.4 La progression dans le TP
Nous allons tout d'abord écrire la partie serveur du projet qui est commune aux deux types de clients :
Nous allons réaliser dans l'ordre :
- la programmation des Arduinos ;
- l'implémentation de la couche [DAO] ; l'implémentation de la couche [métier] ;
- l'implémentation du service REST.
L'objectif principal du TP est de réaliser ce client Android. Ceux qui le peuvent continueront le TP par l'écriture du client web mobile :
1.5 Méthode pédagogique
Les projets " client Android " et " client web mobile " ont tous deux été donnés en projet l'an dernier. Chaque projet a été traité par un groupe de deux étudiants sur une période d'environ 150 h. A la fin du projet, chaque groupe arrivait à allumer / éteindre une lampe connectée à un Arduino. L'objectif est de faire plus en seulement 30 h. Pour y arriver, on vous propose un cadre très contraint dans lequel des squelettes de code vous sont donnés afin que vous puissiez avancer plus vite. Vous trouverez ces éléments dans un dossier [support] :
Par ailleurs, de nombreux codes sont expliqués dans ce document. Faites du copier / coller entre ce document et vos projets Eclipse.
Il est important que vous lisiez et compreniez le document avant de programmer. Avant chaque étape importante du TP, il y a des lectures recommandées. Il ne faut pas faire ces lectures pendant le TP mais chez vous avant le TP. Sinon, vous allez perdre un temps précieux pendant le TP.
Ce TP est également un cours sur la mobilité et plus particulièrement sur Android. Vous ne devez pas vous contenter de coder sans comprendre l'architecture générale de l'application. L'étape normale suivante de ce cours / TP est que ce soit vous qui dessiniez l'architecture générale d'un nouveau projet.
Pour certains, il peut être frustrant de suivre un parcours tracé à l'avance. Vous pouvez alors, si vous le souhaitez suivre votre propre chemin pour réaliser le projet. Vous devez avoir conscience des avantages / inconvénients de cette méthode. En avantage elle est plus créative. En inconvénients, vous aurez moins d'aide de la part des encadrants. Celui-ci n'a pas la capacité de suivre des projets différents alors qu'il le peut si les projets suivent tous la même trame. Il se concentrera donc sur ces derniers. Il y a ainsi le risque de rencontrer des blocages qui peuvent vous retarder.
1.6 Estimation de la durée des différentes étapes du TP
Voici une progression possible du TP :
Tâche Durée
Lectures diverses (en dehors du TP) 20 h
Démarrage TP, Programmation des Arduinos6 h
Couche [DAO] du serveur | 6 h |
Couche [métier] du serveur | 3 h |
Couche [REST] du serveur | 3 h |
Projet Android | 12 h |
Pour arriver à l'objectif final qui est de réaliser le client Android de l'application, il est probable que vous aurez à travailler en-dehors des cours. Les 12 h affectées ci-dessus au projet Android semblent en effet insuffisantes.
1.7 Le matériel
Chaque étudiant aura à sa disposition :
- un Arduino avec une led et un capteur de température ;
- un minihub à partager avec un autre étudiant ;
- un câble USB pour alimenter l'Arduino ;
- deux câbles réseau pour connecter l'Arduino et le PC sur un même réseau privé :
- une tablette Android.
2 Les vues du projet Android
Le client Android permet de gérer les Arduinos à distance. Il présente à l'utilisateur les écrans suivants :
L'onglet [CONFIG] permet de se connecter au serveur et de récupérer la liste des Arduinos connectés :
L'onglet [PINWRITE] permet d'écrire une valeur sur une pin d'un Arduino :
L'onglet [PINREAD] permet de lire la valeur d'une pin d'un Arduino :
L'onglet [BLINK] permet de faire clignoter une led d'un Arduino :
L'onglet [COMMAND] permet d'envoyer une commande JSON à un Arduino :
3 L'exemple à suivre pour le projet Android
Le document [ref2] : Android pour les développeurs J2EE : un modèle asynchrone pour les clients web disponible à l'URL [] est le document de référence pour ce TP, en particulier l'exemple 2. Vous devez lire ce document jusqu'à l'exemple 2 qui décrit l'application suivante :
- l'application lance N [1] tâches asynchrones qui génèrent chacune un nombre aléatoire dans un intervalle [a,b] [2]. Avec une probabilité d'1/3, la tâche peut générer une exception.
- le bouton [4] lance une action unique qui va à son tour lancer les N tâches asynchrones ;
- afin de pouvoir annuler les N tâches lancées, on leur impose un délai d'attente avant de rendre leur réponse, exprimé en millisecondes [3]. Sur l'exemple, le délai de 5 secondes fait que les N tâches sont lancées et toutes attendent 5 secondes avant de faire le travail qui leur est demandé ;
- en [5] remontent les informations produites par les tâches, nombre ou exception ;
- la ligne [6] récapitule ce qui a été reçu. Il faut vérifier qu'on a bien reçu les N réponses des N tâches asynchrones et accessoirement on pourra vérifier la somme des nombres reçus.
Dès que les N tâches ont été lancées, un bouton [Annuler] [6] remplace le bouton [Exécuter]. Il permet d'annuler les tâches lancées :
Cette application a l'architecture client / serveur suivante :
C'est le serveur qui génère les nombres aléatoires affichés par la tablette Android :
Spring / Tomcat
La couche [métier] a une méthode de génération de nombres aléatoires exposée au monde web via un service REST.
Pour tester cette application, on importera sous Eclipse les projets Maven des dossiers [android-avat] et [android-avat-exemple2] des exemples de [ref2] :
Note : ceux qui veulent installer une version d'Eclipse pour Android trouveront dans les annexes de [ref2] la façon de le faire.
En [1] : les projets à importer :
- [android-avat] : le projet de base pour le client Android ;
- [android-dao] : la couche [DAO] du client Android ;
- [android-metier] : la couche [métier] du client Android ;
- [server-metier] : la couche [métier] du serveur ;
- [server-rest] : le service REST du serveur ;
En [2], on exécute le projet web [server-rest] sur le serveur Tomcat [3] :
On peut tester le service REST en tapant dans un navigateur l'URL suivante :
Deux fois sur 3 en moyenne on aura un nombre aléatoire entre 100 et 200 et une fois sur trois en moyenne on aura une exception :
Ensuite on crée une configuration d'exécution pour le projet Android [android-ui2] :
- en [1], sélectionnez l'icône [Run as ] ;
- en [2], sélectionnez l'option [Run Configurations ] ;
- en [3], sélectionnez le type [Android Application] puis l'icône [New launch configuration] ;
- en [4], indiquez le projet qui sera exécuté par cette configuration ;
- en [5], donnez un nom à cette configuration. Peut être quelconque ;
- dans l'onglet [Target] [6], sélectionnez l'option [7]. Elle permet de choisir le mode d'exécution : en mode émulation avec une tablette logicielle ou en mode réel avec une tablette Android ;
- en [8], validez cette configuration ; • en [9], exécutez-la ;
- en [8], sélectionnez l'émulateur de tablette et en [9] exécutez l'application ;
L'émulateur logiciel est alors lancé et affiche la vue suivante :
Pour mettre la bonne URL en [0], on peut procéder ainsi :
- taper la commande [ipconfig] dans une fenêtre [DOS] :
- prendre l'adresse IP [2] de la carte Wifi [1] ;
- déployer le serveur REST sous Eclipse et demander l'URL du service REST avec un navigateur. Utiliser l'adresse IP précédente ;
- l'URL du service REST à taper sur la tablette est alors [192.168.0.14:8080/server-rest]. Il faudra peut-être désactiver le pare-feu du PC voire inhiber un éventuel logiciel antivirus qui pourrait bloquer les connexions entrantes. C'est par exemple le cas de Mcafee.
Branchez maintenant une tablette Android sur un port USB du PC serveur et exécutez l'application sur celle-ci :
- en [1] et [2], sélectionnez la tablette Android ;
Cet exemple sera le modèle à suivre pour le TP à suivre. Etudiez-le et reproduisez-le.
4 Programmation des Arduinos
A lire
- dans [ref2] : l'utilisation de bibliothèques JSON (Annexes, paragraphes 11.1 et 11.2) ;
- dans l'IDE de l'Arduino, tester l'exemple d'un serveur TCP (le serveur web par exemple) et celui d'un client TCP (le client Telnet par exemple) ;
- les annexes sur l'environnement de programmation des Arduinos au paragraphe 13, page 145.
4.1 Les spécifications de la couche [Arduino]
Un Arduino est un ensemble de pins reliées à du matériel. Ces pins sont des entrées ou des sorties. Leur valeur est binaire ou analogique. Pour commander l'Arduino, il y aura deux opérations de base :
- écrire une valeur binaire / analogique sur une pin désignée par son numéro ;
- lire une valeur binaire / analogique sur une pin désignée par son numéro ;
A ces deux opérations de base, nous en ajouterons une troisième :
- faire clignoter une led pendant une certaine durée et avec une certaine fréquence. Cette opération peut être réalisée en appelant de façon répétée les deux opérations de base précédentes. Mais nous verrons aux tests que les échanges de la couche [DAO] avec un Arduino sont de l'ordre de la seconde. Il n'est alors pas possible de faire clignoter une led toutes les 100 millisecondes. Aussi implanterons-nous sur l'Arduino lui-même cette fonction de clignotement.
Le fonctionnement de l'Arduino sera le suivant :
- les communications entre la couche [DAO] et un Arduino se font via un réseau TCP-IP par échanges de lignes de texte au format JSON (JavaScript Object Notation) ;
- au démarrage, l'Arduino vient se connecter au port 100 d'un serveur d'enregistrement présent dans la couche [DAO]. Il envoie au serveur une unique ligne de texte :
{"id":"192.168.2.3","desc":"duemilanove","mac":"90:A2:DA:00:1D:A7","port":102}
C'est une chaîne JSON caractérisant l'Arduino qui se connecte :
- id : un identifiant de l'Arduino, ici son adresse IP ;
- desc : une description de ce que sait faire l'Arduino. Ici on a simplement mis le type de l'Arduino ;
- mac : adresse Mac de l'Arduino ;
- port : le numéro du port sur lequel l'Arduino va attendre les commandes de la couche [DAO].
Toutes ces informations sont de type chaînes de caractères sauf le port qui est un nombre entier.
- une fois que l'Arduino s'est inscrit auprès du serveur d'enregistrement, il se met à l'écoute sur le port qu'il a indiqué au serveur. Il attend des commandes JSON de la forme suivante :
{"id":"identifiant","ac":"une_action","pa":{"param1":"valeur1","param2":"valeur2", }}
C'est une chaîne JSON avec les éléments suivants :
- id : un identifiant de la commande. Peut être quelconque ; • ac : une action. Il y en a trois :
- pw (pin write) pour écrire une valeur sur une pin,
- pr (pin read) pour lire la valeur d'une pin, cl (clignoter) pour faire clignoter une led ;
- pa : les paramètres de l'action. Ils dépendent de l'action.
- l'Arduino renvoie systématiquement une réponse à son client. Celle-ci est une chaîne JSON de la forme suivante :
{"id":"1","er":"0","et":{"pinx":"valx"}}
où
- id : l'identifiant de la commande à laquelle on répond ;
- er (erreur) : un code d'erreur s'il y a eu une erreur, 0 sinon ;
- et (état) : un dictionnaire toujours vide sauf pour la commande de lecture pr. Le dictionnaire contient alors la valeur de la pin n° x demandée.
Voici des exemples destinés à clarifier les scpécifications précédentes :
Faire clignoter la led n° 8 10 fois avec une période de 100 millisecondes :
{"id":"1","ac":"cl","pa":{"pin":"8","dur":"100","nb":"10"}} |
Commande
{"id":"1","er":"0","et":{}} |
Réponse
Les paramètres pa de la commande cl sont : la durée dur en millisecondes d'un clignotement, le nombre nb de clignotements, le n° pin de la pin de la led.
Ecrire la valeur binaire 1 sur la pin n° 7 :
{"id":"2","ac":"pw","pa":{"pin":"7","mod":"b","val":"1"}} |
Commande
{"id":"2","er":"0","et":{}} |
Réponse
Les paramètres pa de la commande pw sont : le mode modb (binaire) ou a (analogique) de l'écriture, la valeur val à écrire, le n° pin de la pin. Pour une écriture binaire, val est 0 ou 1. Pour une écriture analogique, val est dans l'intervalle [0,255].
Ecrire la valeur analogique 120 sur la pin n° 2 :
{"id":"3","ac":"pw","pa":{"pin":"2","mod":"a","val":"120"}}
{"id":"3","er":"0","et":{}}
Commande Réponse
Lire la valeur analogique de la pin 0 :
{"id":"4","ac":"pr","pa":{"pin":"0","mod":"a"}} |
Commande
{"id":"4","er":"0","et":{"pin0":"1023"}} |
Réponse
Les paramètres pa de la commande pr sont : le mode modb (binaire) ou a (analogique) de la lecture, le n° pin de la pin. S'il n'y a pas d'erreur, l'Arduino met dans le dictionnaire "et" de sa réponse, la valeur de la pin demandée. Ici pin0 indique que c'est la valeur de la pin n° 0 qui a été demandée et 1023 est cette valeur. En lecture, une valeur analogique sera dans l'intervalle [0, 1024].
Nous avons présenté les trois commandes cl, pw et pr. On peut se demander pourquoi on n'a pas utilisé des champs plus explicites dans les chaînes JSON, action au lieu de ac, pinwrite au lieu de pw, parametres au lieu de pa, On va découvrir qu'un Arduino a une mémoire très réduite. Or les chaînes JSON échangées avec l'Arduino participent à l'occupation mémoire. On a donc choisi de raccourcir celles-ci au maximum.
Commande Réponse
On a envoyé une commande qui n'est pas au format JSON. L'Arduino a renvoyé le code d'erreur 100.
Commande Réponse
On a envoyé une commande pinread inconnue (c'est pr). L'Arduino a renvoyé le code d'erreur 104.
On ne continuera pas les exemples. La règle est simple. L'Arduino ne doit pas planter, quelque soit la commande qu'on lui envoie. Avant d'exécuter une commande JSON, il doit s'assurer que celle-ci est correcte. Dès qu'une erreur apparaît, l'Arduino arrête l'exécution de la commande et renvoie à son client la chaîne JSON d'erreur. Là encore, parce qu'on est contraint en espace mémoire, on renverra un code d'erreur plutôt qu'un message complet.
4.2 Enregistrement de l'Arduino
A lire
- dans [ref2] : l'utilisation de bibliothèques JSON (Annexes, paragraphes 11.1 et 11.2) ;
- dans l'IDE de l'Arduino, tester l'exemple d'un serveur TCP (le serveur web par exemple) et celui d'un client TCP (le client Telnet par exemple) ;
- les annexes sur l'environnement de programmation des Arduinos au paragraphe 13, page 145.
Au démarrage, l'Arduino doit s'enregistrer auprès d'un serveur de la couche [DAO] sur le port 102 en lui envoyant une chaîne JSON de la forme :
{"id":"192.168.2.3","desc":"duemilanove","mac":"90:A2:DA:00:1D:A7","port":102}
Le code de démarrage de l'Arduino pourrait être le suivant :
1. #include
2. #include 3. #include 4.
5. // ---------------------------------- CONFIGURATION DE L'ARDUINO DUEMILANOVE
6. // adresse MAC de l'Arduino DUEMILANOVE 7. byte macArduino[] = {
8. 0x90, 0xA2, 0xDA, 0x0D, 0xEE, 0xC6 };
9. char * strMacArduino="90:A2:DA:0D:EE:C6";
10. // l'adresse IP de l'Arduino
11. IPAddress ipArduino(192,168,2,3);
12. // son identifiant=IP
13. char * idArduino="192.168.2.3";
14. // port du serveur Arduino
15. int portArduino=102;
16. // description de l'Arduino
17. char * descriptionArduino="duemilanove";
18. // le serveur Arduino travaillera sur le port 102
19. EthernetServer server(portArduino);
20. // IP du serveur d'enregistrement
21. IPAddress ipServeurEnregistrement(192,168,2,1);
22. // port du serveur d'enregistrement
23. int portServeurEnregistrement=100;
24. // le client Arduino du serveur d'enregistrement
25. EthernetClient clientArduino;
26. // la commande du client
27. char commande[100];
28. // la réponse de l'Arduino 29. char message[100]; 30.
31. // initialisation
32. void setup() {
33. // Le moniteur série permettra de suivre les échanges
34. Serial.begin(9600);
35. // démarrage de la connection Ethernet
36. Ethernet.begin(macArduino,ipArduino);
37. // mémoire disponible
38. Serial.print(F("Memoire disponible : "));
39. Serial.println(freeRam());
40. }
41.
42. // boucle infinie
43. void loop()
44. {
45. boolean enregistrementFait=false;
46. // tant que l'arduino ne s'est pas enregistré auprès du serveur, on ne peut rien faire 47. while(! enregistrementFait){
48. // on se connecte au serveur d'enregistrement
49. Serial.println(F("Connexion au serveur d'enregistrement "));
50. if (connecte(&clientArduino,macArduino,ipArduino,ipServeurEnregistrement,portServeurEnregistrement)) {
51. // suivi
52. Serial.println(F("Connecte "));
53. // on envoie l'adresse Mac de l'Arduino, une description de ses fonctionnalités, son port de service 54. sprintf(message,"{\"id\":\"%s\",\"desc\":\"%s\",\"mac\":\"%s\",\"port\":
%d}",idArduino,descriptionArduino,strMacArduino,portArduino);
55. clientArduino.println(message);
56. Serial.print(F("enregistrement : "));
57. Serial.println(message); 58. // enregistrement fait
59. enregistrementFait=true;
60. // on ferme la connexion
61. delay(1);
62. ();
63. // suivi
64. Serial.println(F("Enregistrement termine "));
65. }
66. else {
67. // suivi
68. Serial.println(F("Echec de la connexion "));
69. }
70. }
71. // suivi
72. Serial.print(F("Demarrage du serveur sur l'adresse IP "));
73. Serial.print(Ethernet.localIP());
74. Serial.print(F(" et le port ")); 75. Serial.println(portArduino); 76.
77. // on lance le serveur
78. server.begin();
79. // on attend indéfiniment les clients
80. // on les traite un par un 81. while(true){
82. // placer votre code ici
83. . 84. }
85.
86. }
87. }
88.
89. // connexion au serveur
90. int connecte(EthernetClient *client, byte macClient[], IPAddress ipClient, IPAddress serveurIP, int serveurPort) {
91. // on se connecte au serveur après 1 seconde d'attente
92. delay(1000);
93. return client->connect(serveurIP, serveurPort);
94. }
95.
96. // mémoire libre
97. int freeRam ()
98. {
99. externint __heap_start, *__brkval;
100. int v;
101. return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 102.}
- lignes 1-3 : les fichiers headers des fonctions utilisées dans le code ;
- ligne 1 : pour les fonction de base de l'Arduino ;
- ligne 2 : pour les fonction réseau ;
- ligne 3 : pour la bibliothèque JSON d'écriture / lecture des chaînes JSON ;
- lignes 7-8 : adresse Mac de l'Arduino. Mettez votre propre adresse Mac ;
- ligne 9 : idem sous forme de chaîne de caractères ;
- ligne 11 : adresse IP de l'Arduino. Mettez votre propre adresse IP ;
- ligne 13 : idem sous forme de chaîne de caractères ;
- ligne 15 : le port du serveur de l'Arduino ;
- ligne 17 : description de l'Arduino ;
- ligne 19 : le serveur de l'Arduino ;
- ligne 21 : l'adresse IP du serveur d'enregistrement. C'est l'adresse IP locale du PC auquel vous avez relié l'Arduino, normalement 192.168.2.1 ;
- ligne 23 : port du service d'enregistrement des Arduinos ;
- ligne 25 : le client Arduino du service d'enregistrement ;
- ligne 27 : la chaîne JSON de commande du client ;
- ligne 29 : la chaîne JSON de réponse au client ;
- ligne 32 : la fonction [setup] d'initialisation de l'Arduino ;
- ligne 36 : la carte réseau de l'Arduino est initialisée ;
- lignes 38-39 : on logue la mémoire disponible au démarrage de l'application ;
- ligne 38 : on notera la notation F(chaîne). Cela met la chaîne de caractères dans la mémoire Flash de l'Arduino. Ainsi celle-ci n'est pas placée dans la même mémoire que les autres variables du programme. Cela contribue à libérer de la mémoire pour ces dernières ;
- lignes 97-102 : la fonction freeRam rend le nombre d'octets disponibles dans la mémoire. Cette fonction a été trouvée sur internet. Au départ, on a environ 1100 octets disponibles sur un Arduino de type " uno " ou " duemilanove ". En-deça de 600 octets le programme " plante ". Il faudra appeler régulièrement cette fonction dans votre code pour voir comment évolue la mémoire ;
- ligne 43 : la boucle infinie exécutée par l'Arduino ;
- lignes 47-70 : ce code est exécuté tant que l'Arduino n'a pas réussi à s'enregistrer auprès du serveur d'enregistrement de la couche [DAO] ;
- ligne 50 : on essaie de se connecter. Les paramètres sont les suivants :
- l'adresse du client Arduino de la ligne 25,
- l'adresse IP du serveur d'enregistrement, le port du service d'enregistrement ;
- ligne 93 : notez la façon dont on se connecte à un serveur ;
- ligne 51 : lorsqu'on est là, c'est qu'on a réussi à se connecter au serveur d'enregistrement. On rappelle que l'Arduino doit alors envoyer une ligne JSON du genre :
{"id":"192.168.2.3","desc":"duemilanove","mac":"90:A2:DA:00:1D:A7","port":102}
- ligne 54 : cette ligne est préparée ;
- ligne 55 : elle est envoyée au serveur d'enregistrement ;
- ligne 62 : on ferme la connexion avec le serveur d'enregistrement ;
- ligne 71 : l'enregistrement est terminé. Maintenant l'Arduino va exécuter les commandes que va lui envoyer la couche
[DAO]. Pour cela, on crée un serveur ;
- ligne 78 : un serveur est lancé sur le port 102 de l'Arduino ;
- lignes 81-84 : dans une boucle infinie, vous allez traiter les commandes envoyées au serveur.