Génération de PDF avec CodeIgniter

Introduction

Dans votre application, vous désirez générer un fichier PDF avec vos données, votre charte graphique, etc. Voici un exemple d’utilisation d’une bibliothèque, qui permet de faire :

  • une entête
  • un pied de page
  • ajouter une pagination (numéro de la page en cours ; nombre de page du document)
  • insérer des images
  • insérer du texte HTML

 http://hulan.info/item/html2pdf-convert-your-xhtml-to-pdf-easily

 

Démarrage

Voici comment procéder pour installer cette bibliothèque dans votre projet :

  • Copier dans application/libraries les fichiers :
    • Fpdf_rotate.php
    • Fpdf.php
    • Pdf_html.php
    • Pdf.php
  • Copier dans application/third_party les fichiers :
    • tout le répertoire « fpdf/fonts »
  • Modifier le fichier application/config/config.php avec ces lignes :
//FPDF FONT DIRECTORY
$config['fonts_path'] = APPPATH.'third_party/fpdf/fonts/';

 

 

Générer le PDF depuis votre controller

Définir le point d’entrée du controller (classique CodeIgniter), par exemple « getAttestation() » :

public function getAttestation(){

 

Définir le répertoire des polices :

define('FPDF_FONTPATH',$this->config->item('fonts_path'));

 

Charger les bibliothèques :

$this->load->library(array('fpdf','fpdf_rotate','pdf', 'pdf_html'));

 

Mettre du contenu dans le PDF :

$pdf = new PDF_HTML();

$pdf->Open();
$pdf->SetTopMargin(10);
$pdf->AliasNbPages();
$pdf->AddPage();
$pdf->SetFont('Arial', '', 12);
$pdf->SetDrawColor(0);

$pdf->SetTitle('Attestation');
$pdf->Ln(5);
$pdf->SetFontSize(16);
$pdf->x = 70;
$pdf->Write(0, utf8_decode( "OK") );
$pdf->Output('', 'I'); // I : inline file

 

et terminer la fonction « getAttestation() »:

}

Lorsqu’on lance l’URL de ce controller dans le navigateur, un fichier PDF est généré :

 

Le fichier a pour titre « Attestation », comme prévu par le code.

CodeIgniter + React JS

Introduction

ReactJS est une bibliothèque prometteuse pour changer la façon dont les applications web sont conçues. J’ai retenu une chose importante, ce qui fait la différence par rapport à un appel AJAX simple et classique, c’est que React compare le DOM de la page avant l’appel et après l’appel pour appliquer les changements uniquement sur les modifications.

Il est donc inutile de faire recharger une page complète en cas d’ajout d’item dans une liste, ou même de l’ajouter « à la main » (avec un « append » en jQuery). React s’occupe de faire ces changements.

Soudain, on a envie de passer par cette bibliothèque pour tous les petites modifications à faire sur un écran (notification, compteur) et en exploitant cette technologie à son paroxysme, toute l’application y passe.

 

Quels impacts pour une application MVC ?

Si on prend React avec le framework « Flux », le MVC est mort. Dommage ! Faut-il recoder mes applications avec un autre paradigme ? Pas sûr.

Par contre, une application CodeIgniter qui désire utiliser React doit fondamentalement revoir la signification du V, pour la « Vue ».

En théorie, la vue, c’est ce que que les utilisateurs « voient », donc le HTML qui résulte du serveur hébergeant l’application.

Avec React, la Vue au sens HTML n’est plus à gérer par l’application. React s’en chargera.

Version classique du MVC de CodeIgniter (ou d’autres frameworks)

 

Casser la vue !

Oui, il faut casser la vue. L’application CodeIgniter ne fera que des interactions en manipulant des données JSON, et n’ayant que pour interface technique des WebServices REST.

Une autre application pourra se charger de la vue, des interactions utilisateur et des actions vers le serveur (liste des items, ajout, modification, suppression d’un item). Elle appellera l’application CodeIgniter pour le stockage en base de données, les règles métier, etc.

La partie « vue » de l’application est supportée par une autre application dédiée à l’interaction utilisateur. L’avantage est que si vous avez une application mobile à réaliser, elle pourra interagir avec cette application CodeIgniter en utilisant les mêmes WebServices.

Avec React, la vue peut supportée par une autre application.

Conclusion

La question qu’on peut se poser est la suivante : est-ce utile de s’appuyer sur un Framework MVC pour mon application s’il n’y a plus de Vue ?

S’il y a du boulot côté Modèle ou Controller (ou service) = des objets complexes, des règles métiers, la réponse est oui.

Si c’est une représentation HTML des objets simples en base de données, avec peu de règles métier, la réponse est non.

Données d’un capteur vers un serveur Web

Introduction

Lors de mon précédent article, j’évoque l’envoi des données via Wifi depuis un ensemble de composants autour d’une carte Arduino. Or, la programmation n’est pas très facile pour donner plus d’intelligence à ces capteurs. Je suis donc reparti du capteur de température et de pression DHT11, mais relié à un Raspberry PI.


DHT11 - Cảm biến nhiệt độ và độ ẩm https://images.duckduckgo.com/iu/?u=http%3A%2F%2Fwww.openmediacentre.com.au%2Ffileadmin%2Fuser_upload%2Ftx_onqcatalogue%2Fproduct%2Fraspberry-pi-model-b_80_thumbimg1.jpg&f=1
(les photos ne sont pas à l’échelle)
Prix des composants :

  • Raspberry Pi 2 starter kit (avec les câbles, l’alimentation, une carte SD, des câbles, des radiateurs, un boitier, etc) : 75 € sur Amazon
  • DHT11 (capteur nu) : 2.20 € sur Amazon
  • Dongle Wifi (sur port USB) : quelques Euros (sur eBay)

La programmation est faite en script SH et Python dans le Raspberry et je dispose d’un serveur PHP qui héberge les données (mon PC).

 

Vue du Raspberry avec les câbles pour clavier, souris, écran (inutiles en mode normal, mais nécessaire pour la programmation) + le composant DHT11, relié par 3 fils.

 

Vue des composants minimum pour que les données soient envoyées après avoir tout programmé. Il faudra juste prévoir une boite pour protéger le Raspberry et laisser le capteur « à l’air libre ».

 

Protocole de communication – 1. Souscription

Le Raspberry dispose d’un Dongle Wifi pour se connecter au serveur. J’utilise donc l’adresse MAC du Wifi pour souscrire au serveur selon ce principe :

Dans ces échanges, l’adresse MAC sert de clé. Chaque unité de communication devrait avoir une adresse MAC unique sur le réseau.

Une fois le capteur identifié sur le serveur, il n’est pas encore actif. Le serveur a un capteur en attente de paramétrage manuel (donner un nom compréhensible par un humain, un picto, un groupe, une catégorie, etc…). Tant que cette étape n’est pas faite, les données ne sont pas transmises. Le capteur passe à l’état « Activé » lorsque le paramétrage est terminé.

 

Protocole de communication – 2. Envoi des données

Le serveur est maintenant prêt à réceptionner les données du capteur.

Dans le cas du DHT11, il y a 2 données à chaque envoi : température (en °C) et humidité (en %). Le Raspberry ne fait qu’un appel au serveur pour ces 2 informations.

 

Montage électronique

Le montage sur les PINs du Raspberry sont faits directement car le DHT11 accepte un voltage de 3.3v, fourni par le PIN numéro 1. Si cette alimentation directe n’est pas assez stable, on pourra utiliser un régulateur de tension (AMS1117, 4.70 € les 10 pièces sur Amazon), prenant en entrée du 5v et donnant en sortie du 3.3v stabilisé (monté avec un condensateur de 470µF). Ce sera surtout le cas si on utilise une autre source d’énergie qu’une prise de courant (pile, accu, batterie de voiture, capteurs solaires, etc).

 

Le DHT11 comme capteur

Le DHT11 est un composant assez instable, qui ne garanti pas toujours la bonne lecture des données. Il semble que d’autres capteurs soient plus efficaces, peu onéreux, fonctionnant avec une plus grande plage de voltage : TMP36GT9, DS18B20, etc.

Le DHT11 est par contre bien documenté, pour les bidouilleurs comme moi, devant programmer en Python.

 

Copies d’écran du serveur

Liste des capteurs

 

 

Détail d’un capteur d’humidité

 

Pour aller plus loin

A partir de ce système, il est possible d’équiper toute la maison, d’avoir des capteurs partout et de suivre les courbes. Le budget à prévoir reste collé au prix du Raspberry (carte nue à 40 €), car les capteurs ne coûtent que quelques Euros. D’autres solutions voient le jour, avec des cartes électroniques programmables, comme TESSEL (avec Wifi intégré) : https://www.tessel.io/

D’autres capteurs pourront être ajoutés, sous réserve de pouvoir lire les données (sur le même principe), depuis les ports GPIO du Raspberry. Grâce au grand nombre de PINs disponibles, on pourrait ajouter d’autres capteurs à un même Raspberry, recueillant ainsi un lot de données. Pour une pièce de la maison : température, humidité, ensoleillement, concentration CO2, odeur (oui, pour faire remonter le niveau de puanteur du placard à chaussures), méthane, détecteur de mouvement, etc.

 

Codeigniter 3 chez free.fr

Codeigniter 3

J’utilise le framework Codeigniter pour mes projets personnels, avec mon générateur de code. Sa simplicité d’utilisation et sa rapidité de mise en œuvre restent un atout majeur pour de petites applications web.

En voulant faire une requête de groupe, comme ceci, je me suis confronté à un problème :

select a, b from table1, table2
where table1.c1 = table2.c1
and c1 > 10
or (c2 > 20 and c3 > 30);

 

Les opérations avec les parenthèses sont réalisables de 2 façons :

  1. Faire la requête en SQL pure et la lancer dans CodeIgniter. C’est assez moche et doit être réservé à des requêtes complexes, visant à faire travailler le moteur du SGBD. La requête sera travaillée dans un MySQL Workbench pour être sûr du résultat. On restera alors sur une base de donnée d’un certain type (ex : MySQL), sans pouvoir passer un jour à un autre type (ex: SQLite).
  2. Passer à CodeIgniter 3 pour utiliser la fonctionnalité de regroupements dans les requêtes : voir la documentation dans CodeIgniter

Cette seconde méthode exploite pleinement le SQLBD tout en utilisant le QueryBuilder du Framework. Sauf que pour ça, il faut passer à CodeIgniter 3.

 

Et free dans tout ça ?

L’hébergeur free.fr est gratuit, oui. Mais il est aussi :

  • lent au chargement
  • limité dans l’accès FTP sur le nombre de sessions ouvertes, ce qui est assez pénalisant à l’usage
  • limité dans les bases de données par site (1 seule)
  • ancien, dans les techno qu’il nous mets à disposition
  • permissif, non sécurisé (piratage de compte vécu)
  • sans support (newsgroup étant le seul media d’échange, il reste sans réponse)

Pour que CodeIgniter 3 fonctionne, il doit utiliser PHP 5.2 minimum. Or, chez free, il est à la version 5.1 – dommage !

Pour ces multiples raisons, j’ai ouvert un autre site chez WebHost et j’ai fait un test chez eux.

 

Résultats

A part l’interface de gestion assez « old-scool », on retrouve ses repères. Ouverture de site, ouverture de compte mail, création de base de données MySQL, accès FTP : tout ça se fait très facilement et rapidement.

Mon choix est fait, adieu free, enfin pas pour tout. Je garde mon blog, même si je me sens dans une toute petite boite, sans pouvoir étendre mes jambes ou mes bras (version de WordPress assez ancienne, ne pouvant pas se mettre à jour, pas d’accès aux serveurs externes pour mettre un captcha, etc…).

 

Arduino + ESP8266 + DHT11 : relevé de température vers un serveur HTTP

Introduction

Suite au précédent article qui a permis de faire un HTTP GET sur un serveur en Wifi, grâce au module ESP8266, j’ai ajouté un détecteur de température : le module DHT11, au prix de 2.35 €.

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAEsASwDASIAAhEBAxEB/8QAHAABAAICAwEAAAAAAAAAAAAAAAUGAwQBAgcI/8QAPBAAAQMDAgQEAwcEAAYDAQAAAQACAwQFERIhBjFBURMiYXEUMoEHI0JSkcHRFWKhsSQzQ3KC4RYl8PH/xAAaAQEAAwEBAQAAAAAAAAAAAAAAAQIEAwUG/8QAIhEAAgICAwADAQEBAAAAAAAAAAECEQMSBCExEyJBUWEU/9oADAMBAAIRAxEAPwD2ZERAEREAREQBERAEREAREQBERAEREAREQBERAEXBTKA5RcZXKAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiLjKA4cQ0Ek4AVaud8eZy2neWtaeY6rYv8AdBGw0sTtz85H+lVnvyea9Di8e1vI8vmcpp6QLPb+Iw7EdWMf3j91PMlbK0PY4OaeRC84DyOqkLfdZ6J40Oy3q08ir5uIn3Apg5zXUy9ItK33KG4RameVzfmaei3F5rTi6Z60ZKStHKIigkIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgOFoXa4NoaYkH7x2zQtqeZlPE6WR2GtGVSrlXPrKl0jicdB2C08bD8krfiMnKz/FGl6zVnmdI8uccknJKwFckrple0lR4DduzsEkkEUeoo3GNzj3WUx7YcAQVANeycRGjubXvJ8MnDx6L0ZtdTGmFQJmmI8nZXl9XZmOf4tLiN45t6H+Fv0uuCnEbnknmd9srJm4yySs3YOU8UdX2ejRTRzM1xvDmnqF3VEo7s+3zNIkw0nzN6FXenmZUQMlYcteMhefmwvEz0+PyFmX+mVERcDSEREAREQBERAEREAREQBERAEREAREQBERAEREAREQBcFFAcXcQssVqcWyAVMoIj/tHVx9v94QG27iWzsrzRSV0UcwcWYecAuHMAnZSYe0jIcCPdfNNdWyVlUZiXY5NBOSB/KnLZxFxJYYYn/fOpH40smaS0+x6KVCTDcV+nrHENYDO2lL9I059Cq/KwtO61a26SVlLDVTRGGUx+ZhdnT9VHUl/PxbaN7TJrOG4XtceOuNI+f5UtsrolHBdMLK/nsuG4DTkc1oMhDXav8ADYYozuubRepcCGca2pXWkvcZITn+0rrbqHD8uGA3muMnLbo7wjHW2TpcHt1tzg910C41aRnOAFhp7lTTzugLg145LqcfWaFyZVxO8YNL4x1b091PcMcUy00TaaVhljHLu1dHNLefJa7IYYXufGwNLueFznjjkVM64sssTuJaYeJz8QfFjHhk7Y5hT1PUR1MQlidqaeq82qKltOzUTv0UzwlxBF4rqWeQND92EnbKw8jjRUdono8XlylLWbLsixumjYGl72tDuWTzXcHO4Xnnp2couFyhIREQBERAEREAREQBERAEREAREQBERAERcIDFV1UNFSyVNQ8MiiaXOcegC8G4y4jmvd0le4kNzhrPyNHJv7n19lb/ALSuK9za6V4LInecg/M/t7N/37LzqhtFxushbRUks7ubnNbsPcqUrZPhv8J2QXevMkwzT0+HPH5j0C9DlDS3QWNLRjykbeirPDtmvFidMayB0DZQCDqBBI9vdT7LhDO7RIQ1/dexxktLPC5038tGhdKad0bpIMvIHydVr2S2GlYauob/AMRL0P4B2UxIMdVjzlaaMOx0mmELDITy5LHR3OCqzHIQx4691pXR0uDlpDeQxyURCx5mBGc52wucp06OkMbkrLe9mn26FY+qx0wfHA1r3ZP+lla3UcNO+OXVdEcn6aVfK9rA0Ahp5uwoeueY6aSpgjYx8YHhg8yc8z3VlcwEYcMjqCo6qtTZ5WObJpjz52Y5j0VJxcvDrikovs68O1FyloNVwIO/l/uHdSoBcdljaA1oDRhoHLsom4XGQTAU7gNJ5lSlrGisntK0S81PHUMMcrcj/IUWbXPSzB0DjIwn6tW3RXilncIaiRrKhwzpzvhbj9twchE1ImnBnf4mbwmMklc/QMDJUpbeIJ6QhkpMkXYncKDyTzXIOOqrLFCSpovDNkjLZM9Eo6+Ctj1wvB7jqFsrzylqpaeQSRPLXDsrhZrp8fEWyACVnP1Xl5+M8fa8PX4/KWXp+koi4yuVlNoREQBERAEREAREQBERAEREAREQBV7jDiJthtTjG8CpmBEf9o6u+n+8Kbq6mGipZKmd4ZFE0uc49AF4JxjxFNfLtLIdQadgz8rRyb+59fZPeiUYbTRu4k4higeXNjcS5x6hg3J9z/sr0CeCM0LaODVSws+WOM4GPXuq1wXa5KVpudQXMdKwtiaPy91ZHuycg5C9PBx1VyR5XK5bT1gzQneaKlEQLi0dSVBxsluNxEULyxrDqc4dFZn6XtLXNDgeYKwU9LBRtcIGadZyVuUUlSPNlNydy9M48rAwEkAY3XLA2TIY4Et5jqtWqqPBjwPndy9FBtrpIqjXG4g57pKSRSMXLwsr2AtLXDIPQrUjoYYZvEaPYdllpK74uLzsw4c3BZDuU6fYtx6OskgiYXu5BaFJM2pqTUyyPjhjeGFzCM5PLbqtypp21EZjcSOxCWywMqqeamlnjYcZZnbUf/wXPK2o2jrgipTpqzO6rjFQaWV2ZfwnGCR6hCtGktz6Wokmqah9RP8AIHPdq0tHQFbE1Q2BmojJ6BXhetspkS2pHd7NcZbkjPUKKmt7adr5JCXADOrKm4yydgc0FjiM6HDB+i6Pbza4ZHYqX9iE9WVu12uKsuX9TOdLPlAOxKsZcsbWMjaGxtDWjkAMALnKRio+CUnL055oAcoAsgAaMkKzIOW5bsOZUja6w0dUx4O2d/UKPG255rlrsFZMrUlRuwQcPsejscHsDmnIIyF2UZYZZJbYwyZ2OBnspNeQ1To9qLtWERFBIREQBERAEREAREQBERAFxlcqvcYcQssNpc5jwKmYFsX9vdx9B/vCAqH2mcVgE2qlk8sR+9x+J/b2HP3wqJw3Z3Xe4a5QfAiOqQ9+w+q0pJJrvc2RtJLpXhrNR7nmfqcr0q32yK026OlhHIZc7HzO6lbOLh2dsycvP8cKXrMjiGgNaAGjYAdFiLl2esfVeuj5+77O2VzjK6chk7AKJqOI4aOvjie5pZIdIaeqhtIsk30iTqaRlQ0h2QcYyFDutUsc4GNQJ2cFPwzQVUWuFwO27TzC6u2VXFSLRm4GKGJsMQjb0/ytOvvMNtc3xCCM+bK3JS8ROLBl2NgvPr9LNJWeHNqaeZBVMuT442WxweSR6JSVNNcIRJTSA5GdOd12OWlef8LCsfchHTSObEzzSE8gP5V/1akxT+SN0RlhpKkcZPPmoWpnqZbhGItTHscC33U6GHTqG4PVdQ0CRsmka28nY5LpJWikXUk2dbhxDWzUzKSqpWiVm0bo4/mPqc7Luxz3RN8Y5fjchblfcG10UAdTxsfEDlzfxLSfI2KMyO5BcsUdY/w7cialLp2dvDPPoupbuoFt9mhrXOwTETyVgpaiCtjDmOAdzwV0jNPw5OEl6ctHddue/Qcl3czGyxl3RUySo7YceztnJK27XQPuFY2NoOkbuPYLUiY+aVsbGkuccABXu0W1ltpGswDI7d59Vgy5NV16epjx7P8Aw3IYmQRNiYMNaMBZFwuVhNwREQBERAEREAREQBERAFwuVwThAYauqhoqWWpneGRRNLnOPQBeC8ZcRzXu6SSOOlp2azPyN6N/c+vsrj9pnFYLjaqV+WRO+9IOz39vZvM+uFUeF+HmXBzq6vZrgyQ1pJGs9T7LpixvJKkUyZI4o7SK5SeL8XEYATIHjQB3zsvTBcHUbQ2c6h1HPC0afhyit9c6spmuJx5I3HIYe4Ufd6xzst0nxCcAL1ePieNOzxuVmjma1LOyaCqjEkDw4Hp1C6lq0LHQOt1F94SZZPM8Z+X0W++eGPAkdpJOy0mF+mrXtmdTObAMuxyzzXnD7fWXW4TGdxgljdjw3DdoXqjo9sjcHkQtGroIak5e0teOT2nBXPJDdHbDl+NtkVw5QVdLq+Im8SJoGgnY56qde9rRqc7A7rq0BjQ0DAAwoG+3TQ0xRuU2sceyjvJPosZZ5Q4EEHkRyWhcrTSXKLRUxgkcnjZw+qr1l4lqqZo+JjPw7naRJzb9eytwkbNG2RrS0OGcFVhOOVdFpwnifZoWy2w2ulEEXmOcueebisV6ubLfRudnDiFJY3UHf+H3XVgfDMWSN30u+VytK4x+pSP2l9mQlo4tqqWciYa4XHl2V3gqoa2BssOQCORVLs/DE7ppPi8wmM4aMZ1Hv7K4wQsgibFGMNaMBZ+POcr2/DvyYRi1RlWvWU76iPS1+MdO67SV9NBOIZTjPUdFt6AW62EOaeoWp0+jMrTtEE227+ZuCFGOrpKe4mOEHwmj5u5VtkgEsbmOyARjIOCq0+1Oo6nwyS9rtw49VnjicZWn0bHmWSFNdlhoqwVVMDncc13c7dadFCIGbbZ6KL4lvrbVRlkbgaiUYYPy+qpkkrs74Yuki/cHf0+pnmkbUxSVEJ0mIOGpnqQrgF8oQXCqpagVME8kcwOQ9jiDle5fZxxNebtbWC7ATFxxFIBhxaOrl5c5OTs9WMVFUi/IiKpYIiIAiIgCIiAIiIAiIgCr3GHETbBaXOY9oqpgWxA/h7uPoP4U3VVUVFTSVM7wyKJpc9x6ALwPjPiSW+XaWUktYfK1mfkYOTf3Pr7ISjUoaWbiS+Ni1u0ElznHchvU+5z+pXoghZTQsghYGRsAa1o6AKgcG1U1Le2mOMva9ha/Azgc/pyXpDZYqkb7OPVerxElC0ePz3KU0vw0ycLWkpaeWdk74mukZ8ruoW/NA5h7hazm4W48vtHR8gY0uccAKAvEss1O98cgDgcac7tHdT7gHAtIyFBXiyTT0U8dvk0OmILmk7H2VMm2v1OmLXb7eGHh7iCeaU0oBmDMBzvwkqzvwdwoWwWhlqo2tLfvCN8jdSNTUNp4i9x36KMeyj9icrjs9fDMW7e6r934cdPN8VRSaZRzjdu1ykLdfIarMcwLSDgPxhSb2DSHNILTyIUyjGaplYuUHaKxZaDxJnyvpn0pYdMkX4JD3AKsJeGtJOwC5cFE36qnpaIujic5vUtVMeKOGPRfJllmkrM8F+pHVjqWVwa78J6qUcwFuppDmnkQvM4WtkzUSPEzS7dmrEjSeo7q82mGalp8STPeDy1c8eq44uT8k9aO2XjOEFKzePNdJZfBhc8DJxsuxOSuFsMaf9K1PFLVTF7sklbtHcJbXpbJIcOOAD1UoaRhf4jNj1HQqs3COae6OM7CwR7Mb29VjUZxmb7xzh0XOCqjqofEbgeiwVDWyEauYOQou1eLDsTlpW/JIAC5xwAr5JdkYYKuzXuFfFbqOSolPlYOQ5k9l5fcbhNcaySpndlzjsOw6BW653VlTUGM7wg6S0jZw6lU+so3x3R9JG0udr0tAHNedlyW6R62HHqrZu8OWh95uscRafBacyEdu31X0RwvaWW+3scYwxxGGjHyhUv7OeExTwxukb8p1yn8zuy9QAAAA2Czs7nKIigBERAEREAREQBERAFwuVX+MeI2cPWh0jHj4mYFsI7HG7vYICn/AGncVhpNopn5bGczEfif0b7DmfXC8ubTVNRG+obE97GnzvAyAfVbDnTXi5AayS9xJe88hzLj/klWTh6x1F9q3zUNS6ipaJuiB/IuPc46ncn3wrJfrDZFw0LGQ00tnrWzVbAHTwh5Y5xznDQcagFdYqnMQcWlriM4OxCrV6ss1I//AO0o/BGry11I3yu9XNG36YK7U16FDRYrSamFpwyshOsH0cObT7rbx8kU2mY+Vjckmi301cflkAIKzPgZMNUJ+iiLKW3ssZQTNeZPlPb37KRqKOWzOayWRwkPQ9f/AEt3yRur7PMeGTV10Ynxlp5LERhbrKiGobhwAd3XSamLN+YPIhdUzLKLRpqKuL6hlSx5ZmIHnjIHupdzCDhdC3Iwd/dGrREXTspN2dO+4R0FBlssm79PNg6K40ML6WkZFJIXvA8xPUrBBaqOmrZKuKPTLJzW1LK2KMvceS544ONtnbLkU0kkZm6XO06xqP4eq4fHsQ4Z7gqvSuramfx6c4DckF2wOBnGe6kLVfmVsnws287RuBzarbq6KfHJR2o1qjhmilrY6qPMJa7U5jeTv4UsVlkAHLcd1j0lSoxTtIrKcmqZ1XdvquAMLu1qsVO4GnfmtS4UzKhrXY87eq2S7mf0WJ79lwnPs14sVq2YY2CJgAWrWvLoSAcDr6rS4ivbbTREtIM8m0be3qqdHxZcmsDHlkg/uasWbJXSPT4+JesnZqWMy+JIQyNnme49AtnhKxvvd7fc3sOl8hEI/dV2gdcOJbjHSPeRFnL2sGAB1XvPCNiioKZk/hacN0xN7DusLZtJy20MduomU8YAwNz3K20RQAiIgCIiAIiIAiIgCIuMoDFVVMNJTSVM7wyKJpc5x6ALwLjTiWW/XaSVxIjGzGfkZ0Hv1KuX2n8VhubPSvy1hzOQfmd0b7DmfovM6OLU59ZO3XHGdgfxvPIfufRErZPhlOmgo2wkkT1IDpSBuyPoPc8/bCm7Rea6lp3Pio2T29o/5LT52gfi23HqcLB/8WuNbRNuQAqDIS+VjD5+fToulVcmNAbTMkbUjDWte3BhIxk+m2ds464GF0ILO7iGKtomQ0FU6bxDh0UjfMBjJBPXksFVQUPD9tnuclPFpeAfBdv4kvRvsNzjv7KL4NpZ31bKgNY2ka5w1uG7sDJdnoB/A6qSbJTcW3aWona/+mW8BsUTjs8nOXOOfT/S6x8o5S9s2vs3qqCesqLnDRGjqWgRvbG7MRzvnB5HY/quL/eqmrvb6uUEU7zpiIOWFo5exU9T04PD01zoY2MgZG4t0gDcenZeaX6c0VNDPQHS0gB+ndkg7lp6q0Jay2/hWcdoU/0tjZ2hmphIJ3xnY/VZ6O9lr/DkGW+qp9kvlHURiB9R8JL0ZMcxOP8A3fh+v6q7mOwQ8LfFOqQ24M2cwODiSTsMdsdQtq5EKR58uLNs3g2KqZrhIz+VaskRaSCMFQ1PXyRBsjCC08iOqnKa4RVLQ2bZ35lpTMEoGuWrDPTsqIyx+ceikZqYgam+ZvcLVcwhW9OVNEJVOns9snMUAnfv4bw0k77bjkPdOHbP/TqYzT+aqn80hPT0UxyQLksSUtjvLPKUNDiaoFLEZHY9iuaKsprgzMTwH9W5UNdKkvnEb8sZnB26KI4kiHDVbSyUlZ4xljD8AFux7hRPKoOmWxYJZFaLx4RBwQurtvZRlmv3xsLWyu3I2JUhM8EkDkrSl0Ux47lR0e9RlyukNDTvle4eUZwsldV+EzSPmPJUPia5MqZWwRSFwbu/tlZJy1Vs9LHDZ0iMulxmuda+olPPZo7BazGlxAAyTyC6gbq1cFcPvute2dzcsjcNIxzd/wCl5zbfbPRSS6RePs04UdGPFnjw92HPPYdl62xoY0NaMADAC0rPbWWygZA0ebGXH1W+qFgiIgCIiAIiIAiIgCIiAKB4u4hZw/ZnzNc34mXLIQe/c+g5qammjp4XzSvDI2NLnOJ2AC8G474lkvl2e5riImjTGz8rP5PM/TsoJRXayqNdUySyyknJILty453z68yrBQwUzKikn0/F22Bvm8AanNeebntOCN/8BVQAudjurfScK/BywsF/jo7pIwPihLXN58hr6FdEuiGz1rhqK1S2EfBzR1MLiXFwGMHtjmOXVef8Q24y3T4l0DYaeZpMc78HUwblx9AP46qIgv1Vaa+WK4slpaljtD6ulwMn+9vyvH6LW4n4jfXRthZVsqXvYBJLGwtGkHZuDy7n6JXdj/CUlqI7vYDQ2Cojjl+R1I86JDGOQaTs7J3ON8rBwbJ8N8ZZq2Iw1D3awyVuCdsEb+w/yqU1zgcgkEb5HRTlLxXK6NlPeIG3KBnyvcdM8f8A2yc/1yrp92Va6o9Nb4bbGbdrEMRDgWRtJcR0b2xleX8UEUFOLe/GskYHUNyTk/VSc9RX10Ovh+/1FSDsaSZ2mob7fm9wVTqyOf4pwqxJ42rz+JnVn1yp8uirV1ZzR2yWqZ4oIjiBxqd1PoFM1Mk8NS9sYidqOW6zs4Ach6/wrI74azWe2zsgLmhjHSFr8Zzvj/8AZ3K1Kqjo+I6a43O2uc2Wlc2UwSAZDTs7lz3x0UeMn1EPa74wy+BJ90/PyuOysDJ5ahzY6cEvPJrdyfZUS7wllRG9wAe+MOIB5dlI8LcQ1dluUNUG+MyA6sFaoclx6kZJ8ZS7R6BQXSenIjnB7EFSv3NU0OiOCeYVbvPEzbvdG1HwrKdro25DeZd3P6rLTVZaQWPW3Hk2imzzsuHVuKJeSItOCFixhZqW5RVDQybnyys0tKcameZvcLrZlca8I6emiqYzHK0OB69QqrxDYaya6Gue4SwuAAwPkAGAFdPCwd10fpeC1w8uMYXPJCMu2dcOScXUSqUNKWlvh+XCmKmqdBANZ85HJdGMipvEfkaWlQd1ukcYM0xIGcNA5lc5ySX+I0Qi2/8ATUvV5dBE9g3kkGB6KoElziSckrYq6qSrqHSPJwTsOwWENyvMyZHNnrY8agqNq3UMtwrGU0Qy5559h3Xv/AnDUVsoWTaPlGG5HXuqP9nHCUr52zzx4dIAT/Y1e0xRshibGwYa0YAXFnY7LlEUAIiIAiIgCIiAIiIAiIgKzx02qlsLoKZ+gyO83Y+h9Mrwe4UVXSzOFVG4OJJ1HkV9J3GhjuFI6CQludwR0K87v/D1RS6mVNP4sJ5SAZaVHaZP4edcN0lvrroKa4y+FHIxwZIXYDX42z9Va62nrXWKqfe46aOe3taKOsY4B7iDsNjuPdQldwwS10tE7luWHooCpjqYnaJ9YxyDjtj0XRS6oijtV3OqrpnyVUpke8gknutdjTI8ALqRlZKWOSWdsUbC97zpaBzygNu32qpucxipIy/SMud2C6XS3f01zGvlBc78JGCF6JbqSDhexOkmIa4N1yv7nt+y8yu9xkutwfUyfM92fYdAq33RLVIwsc6N4exzmuactc04IKlG8QSVMYgu0DayNuwkdtI3/wAuZ+qigdwBzXcNL8+Xnvsrpsq0XO33amgtfgRNFypB/wBFxAmiHYg7ELUdxVaLZHUC22lzZp2lkniHSMEEEbH19OQVVBdE8OY4sc05DgcFb8N0pqhvh3am8ZuMCePyyN/Y/VXuylUaNLHPebvHE8kvmfg46D0+i9Ht/DNrrWvoo9NK6NmI9fKV3Yn9/VVO2W0U9xhuVrnbWxRPy6MeWQDrt7K+UstvqKZ5jiZUl/yOMhaYz6t5qa+ovs8/rg+Cd0cY0yRPLXb5B3Wzbbx8RA4vYY3REB7vwknkpS9PpJLnHFHSxtqDGI2xMfkyP/Mew6qCqaQVVXHZ6IF9PSEvqJWb+I/qf2C6QySjVHKeOMrsults9XcrTJc6V8bmQEh8erzAAZytigubosBzstVWNNdra0mF8kdLVRbAv2cM4x/hd7fO+Q6S/BbzBK14czk3Zi5HHjFLUur5Y5gXMIAPQKLuNV4EelvzOXXxvDEZB6brSq3GWRzj/wDxd32Y4LV0RlXVmOJxc7yt3Puqdcq01tRq30t2aFJcQ18b5fh6dxwPmOeagQN15vIy7PVeHrcfFqtn6dgFY+ELGbrcmyOYTFERkHk49AoSkpZaydkETdT3uAAXvHAHDTKGjjldGA2Mbf3O7rKzYi0WG1tttC1paBK8Zd/ClFwuVUBERAEREAREQBERAEREAREQBdXsa9pa8BzTsQRzXZEBV7xwZBVF09A8U8vPR+E/wqNeLI+Fxp7nTmInlIG5B9fVewrBU0kFZEYqiJsjDza4ZU2D52uXDlTSAyxjxoej2bj6jmFYuCbG2GH+p1DPvHHEQPQd1dL1wjBQPbU0lQY2OdgxO3/QqFu9UaWlFNAdEknlaQNm+qN/wskV7jGqmvINHRS/dwO84PJ7u2fRUOSlqKd5bNE5rh3CuUlLPb42tqI8xDcTMOWn1PUfVR15fqoXHIcMbFSopIhuyDo6aapnZBGwukkIwO+VepbLQ2OyGSpGZWty545l3Yei44EsgFKy51MZDy3EYd0HdQvHN+NfcPg4TiCA4yPxO7qrf4iyXVlcfO6ad7iAMnkEyCCN8kLC06Rk8ytqlp5KmZsETS+R5wAOpVih1hdLTSCSGVzHt5OacYUkLpBcH4u8bi9xH/ExDDx7jkf8LYuPDs1rpfFqXBvqOWeygwQ48wrKRDiWemtYt1tqa+1TC4TvGlj4h5omnmS3nlSnDNtNvtImbMwuqNpHYzpPr7KjxTVFFIJqeV8Tu7TjKsdq4rhc7Rcoyx7hg1MA83/k3k4LpFo5yTJW53qtZaY7PX0L4nxSN0T4yx46kHrnmtI0MJu+m0yPdrLRG4txkkZOfQb/AKKaNZLLbXRlwrKFxz4tKdQae7o+Y+n6LVvVwjstpM8LfDqapnhUzcYcyPq8+p/hTF12JLbo0p77RR3KSh+I/wCU7T4p2a89d+m61L5fYoIdFNK2SVwwS05ACp7g7Vk7rq45Ku+RLWjj/wA0Ntg5xe8uJyTuuWjO+F1wpvhyyvu1xbGWnwWHL/4WY1It32ccLvq5m1UrfM8eUEfK3uvb6enZTQMhjGGsGAojhiyx2m3M8gEjwM+g7KcVGSEREAREQBERAEREAREQBERAEREAREQBcOcGgknAC5UJf7j4Mfw0Z8zhlxHQIF2RV5r/AIqoLgSWM2aO63LTw7TzUj5bhA2R04+Vw+UenZa9mt3x1QJpG/dRnOO5VrAAGByQs3+FLuXBctOHSWuTWw84ZP2P8qk1PC8VZX+BUU8lK5rg6SMbNcPb+F7S5wY0uJwANyqfd674qpdIBs3ytCWEiqcRXBtst7KKm8j5BoBb/wBNvdVyooaOppmxvia4NGxxuPqrxV8H3R8RuEZbO6UeaF3MN7Duq1UWwMf4bWGllb8zHg4P06K0eg3ZRq2iipaqONpJaXY8yu/BPD4o6c3GqZh7xiMO5gd/qoqPh2pul+iinidHTxed7+jh2BVpv1wbSU7LfA7EkzceU40N7qrd9IlL9KZxjfmVte+mhw+GHygn83Uqst2apGusNTBIXMPjMPUcwteGllE+Hx/JzaVZKirdszUNufWODHEsa7YPI2BWlKwRvc0O1YJGRyK3Z6wxHwiTlw2AJwFqYyrXRX0yUNxq7bO2eknfE8Hm08/fuu9zutXd6v4msk8STAbywAPQLWLOy64VrK0cHYFYT0WV/wAq6NYXOAUMlGWkpZKiZrGMLnOOAB1Xt/2fcMMp6eOWSMaWeZx/M5UrgHhuSsqo6hzdycMGOQ6le50dLHR0rIIwA1gwubLGZcoigBERAEREAREQBERAEREAREQBERAEREBr1lSykp3Su6DYdyqm1k1yreeXPdut++zTTVYgDXFjRkFu4+vZSNmt4pYBI8edw/QIW8RvUtOylgbEwbAfqsqLXrqtlHTOldzHIdyhUjb9X6GfCxnzO+YjoFo2W3fFVHjyt+6j5A9StaKOa51nUl53PZW2mgZTQNiYMBoQs+ujJhR11s9uuULvjIWnSPnGzm/VSKguIbhpZ8LG7c7vPp2QhIqxp4bdFJ4LnyNaTpJ3J7KszUclXUPqC8iof80bxjA6Adl6BY7b8dUCplb9zGdgRzKmrlYLfc2/fQhsgG0jNnD6ov6S3+HjM7JqYPbIzBIxuMj6KqSVgguE73bsIwT6r2O68H11Mx/hMFbBjkNnj6Lzu6cLxS62UzjEdWTFISN/f+cq9lSnVdS2qnY9gIxtuFnxss01kqKKYtkYcjcDG6xluFAOMLqW5U/Z7tbIqT+n3W3Nmgc/V48e0rPbutG7wW+Crxbap1RA4ZBezSW+ikEW+MnkpOxWl1wrWxgHQN3kdlqRxukeGNGXOOAB1Xr32e8LtjYHzMyG+Z5PU9kbFFs4SsbLXb2yFuHvaMD8oVhXAAAAAxhcqgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgNZ1Gxz863ac5LM7ErYAwFyiA4JAGTyVVu1aa+q8OPJjYcN9fVWapY59O9rQCSOR6qIoLSxtUZNL9Dejxjf09EJXRtWigFJTh7h94//AUkuEJAGTyQg16+rbR0zpTz5NHcqpRQzXOt08y92XFbd3rjWVXhx7sYcD1KmbNbxR0we4feP3PooLeI3KanZTQNijGA0LMiKSoUTduHLfd2kzxBsvSRmzgpZEB5td+DKynaR4Qrqcb5x5h9P4VKruGBNqdTHLhzY7Zw+v8AK99O6iLpw1Q3Iuk0eDOeUsex+vdTf9B871VsqKV5aWE6eYxgj6LTIXsd14VqadpFXTiphbuJoxuP3CrEnCEFVUgsdmMncjZw/lSDS4K4blrqqOpczOTiMY/yvc6CijoKRkEYxpG57lRHC1lit1I2QRhp04YOwVhVQEREAREQBERAEREAREQBERAEREAREQBERAEREAREQBcLlEAUTf640lCQw+ZwPIZKllimp4p26ZGg/sgIGyW0ySePM3ZvT1ViXWKJkMYYwYaF3QluwiIhAREQBERAcYB2UdNYrfNUtqPADJAcnRsD7hSSIDgANAAGAFyiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA//Z

Ce module intègre des résistances pour assurer son bon fonctionnement. On peut trouver le composant sans la plaque où celui-ci est soudé, mais il faudra ajouter les composants électroniques nécessaires lors du branchement.

 

 

Connexion

De multiples articles décrivent comment faire un relevé de température avec le module DHT11. Il faut penser à le brancher sur le 5v et laisser le 3.3v pourESP8266.

L’article suivant décrit ce qu’il faut faire pour stabiliser les tensions : https://github.com/esp8266/Arduino/blob/master/doc/boards.md#improved-stability

J’ai juste ajouté un condensateur de 100µF pour éviter les reboot intempestifs du composant ESP8266 (pour cause d’instabilité du signal).

 

Code complet

Voici le code pour Arduino :

#include <SoftwareSerial.h>
#include "DHT.h"

/** DHT **/
#define DHTPIN 5
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

/** ESP8266 **/
String ssid = "NETGEAR";
String key = "xxxxxxxx";
String serverHost = "192.168.1.100";
String serverPort = "80";

SoftwareSerial esp8266(1, 0); // RX, TX
bool done = false;

void setup() {

  /** DHT **/
  dht.begin();

  /** ESP8266 **/
  esp8266.begin(115200);
  delay(500);
  esp8266.println("AT+RST");

  /**
   * Initialisation
   */
  delay(1000);
  esp8266.println("AT");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Se mettreen mode CLIENT
   */
  esp8266.println("AT+CWMODE=1");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Connexion auWifi
   */
  esp8266.println("AT+CWJAP=\""+ssid+"\",\""+key+"\"");
  done = esp8266.find("OK");
  while(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Se mettre en mode multiple connexions
   */
  esp8266.println("AT+CIPMUX=1");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Récupération de l'adresse IP
   */
  esp8266.println("AT+CIFSR");
  done = esp8266.find("STAIP");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

}

void loop() {
  int maxLoops = 5;

  /**
   * DHT11 : Temperature
   */

  float temperature = dht.readTemperature();
  if( isnan(temperature) ){
    return;
  }
  // convert float --> String
  String temperatureStr = "";
  char temperatureChar[15];
  dtostrf(temperature,5,2,temperatureChar);
  temperatureStr = temperatureChar;

  /**
   * HTTP GET
   */
  String cmd = "AT+CIPSTART=4,\"TCP\",\""+serverHost+"\","+serverPort;
  esp8266.println(cmd);
  delay(500);
  done = esp8266.find("OK");
  int currentLoop = 0;
  while(!done){
    delay(500);
    done = esp8266.find("OK");
    if(currentLoop >= maxLoops){
      break;
    }
    currentLoop++;
  }

  String url = "/lda/index.php/data/createdatajson/append?datflval="+
    temperatureStr +
    "&thing=FIRST";
  String cmdGET = "GET " + url + " HTTP/1.1\r\n"+
    "Host: "+serverHost+"\r\nUser-Agent: ESP8266_HTTP_Client\r\nConnection: close\r\n\r\n";
  esp8266.print("AT+CIPSEND=4,");
  esp8266.println(cmdGET.length());
  delay(1000);
  done = esp8266.find(">");
  currentLoop = 0;
  while(!done){
    delay(500);
    done = esp8266.find(">");
    if(currentLoop >= maxLoops){
      break;
    }
    currentLoop++;
  }
  esp8266.println(cmdGET + "\r\n\r\n");
  delay(1000);

  esp8266.println("AT+CIPSTATUS");
  delay(1000);

  // Fermeture de toutes les connexions
  esp8266.println("AT+CIPCLOSE=5");
  delay(1000);

  // repart à zero
  esp8266.println("AT");

  // 4 secondes sont déjà passées
  delay(16000);

}

 

 

Annexe

Photos du projet avec la platine d’essai :

 

Arduino + ESP8266 : connexion Wifi

Introduction

La carte Arduino peut être connectée à un module de connexion Wifi (nommé ESP8266) pour lequel une configuration est nécessaire.

Voici la façon dont j’ai pu envoyer un simple HTTP GET depuis la carte Arduino avec ce module.

Dans certains tutoriels qu’on peut trouver sur le Net, il est mentionné la mise à jour du firmware, par l’intermédiaire d’une autre carte électronique. Cet article part du module sorti de son emballage, sans faire cette mise à jour.

 

Le module ESP8266

Ce module est un regroupement de multiples composants, sous forme de mini-carte électronique, avec 8 broches de connexion.
Il mesure 2.5 cm x 1.5 cm et coûte 7.33 € sur Amazon.

Il permet de se connecter à un point d’accès Wifi pour communiquer en mode client/serveur (être client ou être serveur) mais il peut aussi être défini en tant que point d’accès Wifi.

Branchements

Il faut brancher le composant avec la carte Arduino, de manière précise, sur le 3.3v.

 

Détail des branchements :

L’article http://www.labradoc.com/i/follower/p/notes-esp8266 détaille les branchements. En voici un rappel (en Français) :

  • RX vers le port TX de la carte Arduino
  • VCC vers le port 3.3v de la carte Arduino
  • GPIO 0 non branché
  • RESET non branché
  • CH_PD vers le port 3.3v de la carte Arduino
  • GPIO 2 non branché
  • TX vers le port RX de la carte Arduino
  • GND vers le port GND de la carte Arduino

Si vous avez branché RX et TX correctement, une LED bleue sur le module ESP8266 émet un bref flash lors de la mise sous tension. Si elle ne s’allume pas, c’est que le branchement n’est peut-être pas bon…

Quelques conseils :

  • Branchez tout et à la fin, le fil qui va vers 3.3v. Vous saurez si tout est opérationnel ou non avec cette LED bleue.
  • Il ne faut rien brancher avec le port 5v de la carte Arduino. En cas d’erreur, le module grillera. Je vous conseille donc de brancher un fil sur ce port 5v et de laisser non branché à l’autre bout du fil (par exemple, faire un nœud pas trop serré).

 

Comment donner des ordres au module ESP8266 ?

L’article http://www.labradoc.com/i/follower/p/notes-esp8266 détaille les commandes à passer par l’interface de programmation d’Arduino. Pour résumé, une série de commandes doivent être passées pour :

  • Initialiser le module ESP8266
  • Se mettre en mode client Wifi (et pas en mode point d’accès)
  • (en option) Rechercher les points d’accès disponibles (et afficher leur SSID)
  • (en option) Se définir une adresse IP
  • Se connecter sur un point d’accès (avec SSID et mot de passe)
  • Se mettre en mode « Connexions multiples » (pour faire plusieurs appels HTTP)
  • (en option) Afficher son adresse IP
  • (en option) Faire un PING sur un serveur
  • Faire un HTTP GET
  • Fermer la connexion (et préparer le prochain appel HTTP)

Ces commandes sont à transmettre par le port Série de la carte Arduino.

 

Code pour faire les appels HTTP GET

Avec Adruino, 2 fonctions sont préparées pour que l’utilisateur écrive son code à l’intérieur, avec 2 objectifs :

  • setup() : cette fonction est lancée une seule fois au démarrage de la carte Arduino
  • loop() : après la fonction « setup() », cette fonction est lancée autant de fois que la carte Arduino est allumée

Une partie d’initialisation est faire avant ces 2 fonctions

#include <SoftwareSerial.h>

String ssid = "NETGEAR";
String key = "pA$$W0Rd";

SoftwareSerial esp8266(1, 0); // RX, TX
bool done = false;

Seule la bibliothèque SoftwareSerial est nécessaire.

La variable « done » sera utilisée de manière globale.

 

Code de la fonction setup()

 void setup() {
  // put your setup code here, to run once:

  esp8266.begin(115200);
  delay(500);
  esp8266.println("AT+RST");

  /**
   * Initialisation
   */
  delay(1000);
  esp8266.println("AT");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Se mettre en mode CLIENT
   */
  esp8266.println("AT+CWMODE=1");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Affecter son adresse IP manuellement
   */
   /*
  delay(1000);
  esp8266.println("AT+CIPSTA=\"192.168.1.200\",\"192.168.92.254\",\"255.255.255.0\"");
  done = esp8266.find("OK");
  while(!done){
    delay(1000);
    done = esp8266.find("OK");
  }*/

  /**
   * Rechercher les points d'accès WIFI
   */
   /*
  delay(1000);
  esp8266.println("AT+CWLAP");
  done = esp8266.find("OK");
  while(!done){
    delay(1000);
    done = esp8266.find("OK");
    delay(3000);
    break;
  }*/

  /**
   * Se connecter au point d'accès Wifi défini dans la variable "ssid"
   */
  esp8266.println("AT+CWJAP=\""+ssid+"\",\""+key+"\"");
  done = esp8266.find("OK");
  while(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * Se mettre en mode connexions multiples
   */
  esp8266.println("AT+CIPMUX=1");
  done = esp8266.find("OK");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * afficher son adresse IP
   */
  esp8266.println("AT+CIFSR");
  done = esp8266.find("STAIP");
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }

  /**
   * faire un ping sur un server
   */
   /*
  delay(1000);
  esp8266.println("AT+PING=\"192.168.1.100\"");
  done = false;
  if(!done){
    delay(1000);
    done = esp8266.find("OK");
  }*/

}

Il est nécessaire de mettre des temps d’attente (moins une seconde maxi) pour que le module se mette dans un état convenable, qu’il communique avec le point d’accès Wifi. Sinon, vous aurez des messages du genre « busy p… » ou « busy s… », qui peuvent être bloquant ou non.

Ajustez ces temps selon vos résultats.

 

Code de la fonction loop()

void loop() {
  int maxLoops = 5;

  /**
   * Faire un HTTP GET
   */
  String cmd = "AT+CIPSTART=4,\"TCP\",\"192.168.1.100\",80";
  esp8266.println(cmd);
  delay(500);
  done = esp8266.find("OK");
  int currentLoop = 0;
  while(!done){
    delay(500);
    done = esp8266.find("OK");
    if(currentLoop >= maxLoops){
      break;
    }
    currentLoop++;
  }

  String url = "/lda/index.php/data/createdatajson/append?datflval=1.55&thing=FIRST";
  String cmdGET = "GET " + url + " HTTP/1.1\r\n"+
    "Host: 192.168.1.100\r\nUser-Agent: ESP8266_HTTP_Client\r\nConnection: close\r\n\r\n";
  esp8266.print("AT+CIPSEND=4,");
  esp8266.println(cmdGET.length());
  delay(1000);
  done = esp8266.find(">");
  currentLoop = 0;
  while(!done){
    delay(500);
    done = esp8266.find(">");
    if(currentLoop >= maxLoops){
      break;
    }
    currentLoop++;
  }
  esp8266.println(cmdGET+"\r\n\r\n");
  delay(1000);

  esp8266.println("AT+CIPSTATUS");
  delay(1000);

  // Close all connections
  esp8266.println("AT+CIPCLOSE=5");
  delay(1000);

  // restart from zero
  esp8266.println("AT");

  // 4 secondes déjà passées
  delay(20000);

}

 

Je désire faire l’appel à l’URL « http://192.168.1.100:80/lda/index.php/data/createdatajson/append?datflval=1.55&thing=FIRST » en GET. Tous les paramètres de cette requête sont après le caractère « ? ».

J’ai un serveur HTTP qui est capable de lire cette requête et de stocker la valeur « 1.55″ pour un objet « FIRST » dans une base de données.

Ce code se découpe en plusieurs parties :

  1. Se connecter au serveur 192.168.1.100, en mode TCP, sur le port 80 : « AT+CIPSTART=… ». Il faut attendre que le moduleESP8266 réponde « OK » pour continuer.
  2. Appeler l’URL en GET : « AT+CIPSEND=… ». Il faut absolument ajouter dans l’entête de cette requête le « Host: xxx », sinon le serveur répond « Error HTTP 400 : BAD REQUEST ». Pour être propre, je rajoute « User-Agent » et « Connection ». Les « \r\n » sont importants. A la fin, il faut les mettre en double : « \r\n\r\n ». Sinon, le serveur attend des données.
  3. (En option) Demander le statut de la connexion : « AT+CIPSTATUS ». elle doit être fermée (le serveur a pris la requête est il a fermé la connexion)
  4. S’assurer que toutes les connexions sont bien fermées : « AT+CIPCLOSE=5″ (le chiffre 5 signifie ‘toutes les connexions’)
  5. Réinitialiser le module ESP8266 : « AT ». Lors de la prochaine connexion au serveur (étape 1 de la boucle), la connexion Wifi sera conservée.
  6. Attendre 20 secondes pour le prochain envoi de données

Ici aussi, les délais d’attente entre les commandes sont importants. Ils peuvent être personnalisés selon votre besoin, mais ils ne pourront pas être mis à 0.

 

Envoi vers la carte Arduino

Les ports TX et RX sont utilisés lors du transfert du programme vers la carte Arduino. si vous laisser le 3.3v branché, Il faudra débrancher les TX et RX pour que le transfert se fasse correctement. Je réitère donc mon conseil de débrancher le 3.3v lors du transfert.

 

Résultat sur le serveur

Les données sont toutes récupérées, à intervalle régulier (toutes les 24 secondes) :

 

Trace laissée par le module

Dans la console « Moniteur série », voici les infos affichées par le module. On y trouve les commandes passées et les réponses du module.

Ai-Thinker Technology Co.,Ltd.

ready
AT

OK
AT+CWMODE=1

OK
AT+CWJAP="NETGEAR","pA$$W0Rd"

WIFI CONNECTED
WIFI GOT IP

OK
AT+CIPMUX=1

OK
AT+CIFSR

+CIFSR:STAIP,"192.168.1.200"
+CIFSR:STAMAC,"5c:cf:7f:10:d6:ab"

OK
AT+CIPSTART=4,"TCP","192.168.1.100",80

4,CONNECT

OK
AT+CIPSEND=4,157

OK
> 

busy s...

Recv 157 bytes

SEND OK

+IPD,4,728:HTTP/1.1 200 OK
Date: Sat, 16 Jan 2016 17:32:03 GMT
Server: Apache/2.4.12 (Ubuntu)
Set-Cookie: ci_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%227c75547487eb7803fa0afe75dead178d%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22192.168.1.200%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A19%3A%22ESP8266_HTTP_Client%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1452965523%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7Deb938672b48c15066e92aef755ab6250; expires=Sat, 16-Jan-2016 19:32:03 GMT; Max-Age=7200; path=/
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
Content-Length: 81
Connection: close
Content-Type: text/html; charset=UTF-8

{"datiddat":41,"datflval":"1.55","datdhacq":"2016-01-16 18:32:03","datidthn":"1"}4,CLOSED
AT+CIPSTATUS

STATUS:4

OK
AT+CIPCLOSE=5

OK
AT

OK
AT+CIPSTART=4,"TCP","192.168.1.100",80

4,CONNECT

OK
AT+CIPSEND=4,157

OK
> 

busy s...

Recv 157 bytes

SEND OK

+IPD,4,728:HTTP/1.1 200 OK
Date: Sat, 16 Jan 2016 17:32:27 GMT
Server: Apache/2.4.12 (Ubuntu)
Set-Cookie: ci_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%220a10f1ca33ba3316e6acfee18ba76b2f%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A13%3A%22192.168.1.200%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A19%3A%22ESP8266_HTTP_Client%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1452965547%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7Db946991f8b9d1ef88d0667330b515767; expires=Sat, 16-Jan-2016 19:32:27 GMT; Max-Age=7200; path=/
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
Content-Length: 81
Connection: close
Content-Type: text/html; charset=UTF-8

{"datiddat":42,"datflval":"1.55","datdhacq":"2016-01-16 18:32:27","datidthn":"1"}4,CLOSED
AT+CIPSTATUS

STATUS:4

OK
AT+CIPCLOSE=5

OK
AT

OK
...

 

Annexe

Toutes les commandes et la doc technique (en anglais) de ce module ESP8266 : https://nurdspace.nl/ESP8266

Code complet : téléchargez

 

Raspberry : un feu de cheminée ou un aquarium

Introduction

Noël approche, qui n’a pas rêvé d’avoir un feu de cheminée. Je vous propose de transformer votre Raspberry en « boite à diffuser une vidéo de distraction », comme un feu de cheminée, un aquarium ou une jolie vue de ruisseau.

 

Configuration du Raspberry

Rien de plus qu’un Raspberry qui fonctionne et qui est connecté à un écran.

 

Choix de la vidéo

Youtube fourni un grand nombre de vidéos, en HD de feu de cheminée ou d’aquarium. Voici mon choix :

https://www.youtube.com/watch?v=0fYL_qiDYf0

La vidéo dure 2 heures, mais on n’a besoin de tout le fichier. Il faut passer par une outil de téléchargement (cherchez « youtube downloader firefox plugin ») pour récupérer le fichier MP4.

 

Extraction d’une portion de quelques minutes

Passez par ffmpeg pour extraire une partie de la vidéo. Notez la période : début et durée, puis lancer la ligne de commande suivante pour l’extraction :

ffmpeg -ss 00:30:00 -i feuDeCheminee-full.mp4 -t 00:02:00 -vcodec copy -acodec copy feu-portion.mp4

Sur la vidéo « feuDeCheminee-full.mp4 », je saute 30 minutes du début et je prends 2 minutes de vidéo finale. Le fichier « feu-portion.mp4 » contiendra le résultat : une vidéo de quelques dizaines de Mo (au lieu de plus d’un Go pour la vidéo complète).

 

Lire la vidéo avec le Raspberry

Tentez de lire la vidéo avec VLC : c’est très lent. Impossible de choisir cette solution. En allant voir sur le Net, le player conseillé est « omxplayer ». Cherchez à l’installer avec les bibliothèques pour être sûr du résultat.

Mon Raspberry est configuré en point d’accès Wifi, avec une application Web pour le piloter (depuis mon smartphone ou depuis un PC). J’ajoute cette fonctionnalité, en appelant un script pour lancer la vidéo :

#!/bin/bash

export DISPLAY=:0.0

SERVICE='omxplayer'
RES=0
trap "exit" INT
while [ $RES -eq 0 ]; do
  if ps ax | grep -v grep | grep $SERVICE > /dev/null
  then
    sleep 1
  else
    xterm -fullscreen -fg black -bg black -e omxplayer --win "0 0 1600 1200" -r $1
    RES=$?
    echo "RES: $RES"
  fi
done

xrefresh -display :0

 

Vous constaterez des lignes particulières (que j’utilise peu) :

trap "exit" INT

Cela signifie que si un sous-script est lancé et qu’il se fait killer, le script s’arrête aussi.

 

xrefresh -display :0

A la fin du script, je force le rafraîchissement de l’écran pour nettoyer ce qui peut rester.

 

xterm -fullscreen -fg black -bg black -e omxplayer --win "0 0 1600 1200" -r $1
RES=$?

La ligne de commande principale, qui lance la vidéo, dans un terminal (xterm), en plein écran, avec omxplayer en mode fenêtre, d’une taille de 1600×1200. La variable RES récupère le code retour du player. Si elle vaut 0, on boucle, sinon, on s’arrête (le CTRL-C fait un RES = 2).

Pour simuler la lecture sans fin, j’ai une boucle while autour de tout ça.

 

Arrêt de la lecture par un script

J’ai aussi un autre script qui arrête la lecture en boucle :

PID=$(ps aux | grep omxplayer | awk {'print $2'})
kill -9 $PID 2>/dev/null

xrefresh -display :0

Rien de très novateur. J’ai essayé la commande « killall -9 omxplayer », mais elle n’est pas satisfaisante.

Mon interface (depuis un PC) pour lancer quelques vidéos et un bouton en bas pour arrêter :

Arduino : premiers essais

Introduction

Après avoir complètement paramétré mon Raspberry Pi en point d’accès wifi, avec une webcam et une application web pour le piloter depuis mon smartphone (article complet), je voulais essayer jouer avec les PIN du GPIO. Mais je ne voulais pas refaire un autre Raspberry pour jouer avec les « sensors » (détecteur de température, détecteur de mouvement, etc.). Pour faire ça, il y a Arduino, en plus simple et plus économique…

 

 

Installation de l’environnement

Depuis longtemps, je suis habitué à l’IDE Eclipse pour mes développements. J’ai pris mes réflexes et je pense être moins désorienté dans ces environnement. C’est pour cette raison que j’installe un Eclipse dédié.

J’ai donc suivi quelques tutoriels, mais celui-ci me semble très complet pour tout savoir sur l’interface entre ma machine et la carte Adruino : http://www.codeproject.com/Articles/1003347/Creating-Arduino-programs-in-Eclipse

Avec Ubuntu, le port est à changer. Pour savoir quel port il faut configurer (« //./COM15″ dans le tutoriel), voici les étapes, depuis un terminal :

  1. Branchez votre carte Arduino sur le port USB et tapez « lsusb ». Si une ligne apparaît avec « Arduino », c’est bon, la carte est reconnue.
  2. Tapez « dmesg ». Vous devriez voir :
    [ 1013.247248] usb 8-2: Product: Arduino Uno
    [ 1013.247250] usb 8-2: Manufacturer: Arduino Srl
    [ 1013.247253] usb 8-2: SerialNumber: 85431303636351D0A101
    [ 1013.272419] cdc_acm 8-2:1.0: ttyACM0: USB ACM device
  3. Tapez « ls /dev/ttyACM* ». Vous devriez avoir le port de l’Arduino : /dev/ttyACM0
  4. Il reste à permettre à l’utilisateur d’écrire dans ce device : sudo chmod 777 /dev/ttyACM0

 

Premier script : « blink »

En suivant le tutoriel, je crée le programme « blink.cpp » en copiant / collant le code fourni, mais une erreur survient sur l’include :

#include "arduino.h"

 

Il faut la changer en :

#include "Arduino.h"

En consultant le fichier recherché dans mon code (version 1.6.6 d’Arduino), il y a un « A » (majuscule).

Le build se passe correctement et l’installation sur la carte aussi. La LED clignote bien.

 

Conclusion

Même si l’IDE fourni par Arduino fonctionne très bien, il m’a fallu un peu plus d’une heure pour installer quelques plugins et adapter le dernier. J’espère que cet article fera gagner du temps à ceux qui essaieront.

 

OpenCV pour mesurer la qualité des images – update

Introduction

Un premier article (OpenCV pour mesurer la qualité des images) a été rédigé il y a fort longtemps sur la mesure de qualité d’une image ou d’une photo, par rapport au flou ou au défaut de mise au point. A vrai dire, je n’étais pas complètement satisfait du résultat, en comparant 2 photos ayant de légères différences de netteté. Après d’autres recherches et tests, voici une version nettement améliorée.

 

Le script v2

import cv2, sys

filepath = sys.argv[1]
filename = sys.argv[2]

myCamera = cv2.VideoCapture(0)
if myCamera.isOpened():
    ret, frame = myCamera.read()
    gray = cv2.cvtColor( frame, cv2.COLOR_BGR2GRAY)
    variation = cv2.Laplacian(gray, cv2.CV_64F).var()

    finalFilename = "%s/%d-%s" % (filepath, variation, filename)
    cv2.imwrite(finalFilename, frame)

 

Notes et remarques

Ce script donne un autre résultat, en se basant sur une image en tons de gris et en calculant le laplacien. Ensuite, il calcule la variation sous forme d’un scalaire, donc facilement exploitable pour trier les photos nettes de celles qui le sont moins.

Ce script est utilisé pour un mode « rafale » de prises de vues sur une webcam (derrière un télescope), pour isoler les photos les plus nettes. L’indice de qualité est le préfixe du nom de fichier, donc c’est facile d’avoir les 50 meilleures photos et les 50 les plus floues.

 

Raspberry Pi + Camera : pilotage par un smartphone

Intérêt

Le raspberry est une petite boite contenant l’équivalent d’un PC assez puissant pour faire quelques petites choses intéressantes. L’objectif est de brancher le raspberry sur une source d’alimentation (dans la voiture, près de la télé, sous un télescope) et de piloter quelques actions depuis un smartphone.

Exemples d’application :

  • Près d’un point de surveillance de la maison : Caméra de surveillance, avec enregistrement des vidéos sur une clé USB
  • Dans la voiture : Enregistrement de la conduite de manière automatique. en cas de litiges, vous aurez un enregistrement vidéo
  • Sous un télescope : avec une webcam derrière l’objectif pour faire la mise au point et une série de prises de vue enregistrées sur la clé USB
  • Près d’un moniteur ou d’une télé : pour lancer une présentation PowerPoint / PDF, pour jouer des vidéos, avec la webcam pour prendre des photos

Tout ça, avec un smartphone en guise de télécommande Wifi.

 

Configuration matérielle pour le démarrage

Voici le matériel nécessaire pour configurer le Raspberry complètement :

  • Un clavier USB
  • Une souris USB
  • Un écran
  • Une clé USB
  • Un accès à Internet

 

Configuration logicielle pour le démarrage

  1. Installation de l’image Ubuntu Mate pour Raspberry
  2. Installation des services :
    1. LAMP (Apache + PHP + MySQL), avec changement du user apache
    2. openssh-server (pour accès shell par SSH)
    3. usbmount (auto-mount les clés USB)
  3. Configuration des points de montage : pour la clé USB :  « uid=1000,noauto,user »
  4. Désactivation du firewall Ubuntu
  5. Installation d’un serveur FTP et SSH pour déposer les fichiers depuis un autre PC et lancer des lignes de commandes

 

Configuration logicielle étape 2

Cette étape se fait depuis un PC pour plus de confort. On a donc mis le Raspberry sur un réseau interne :

  • Un PC connecté via RJ45 à un routeur
  • Le Raspberry connecté en RJ45 au routeur

Par la suite, le câble RJ45 sera supprimé.

 

Le clavier, la souris et l’écran peuvent être supprimés après avoir installé les serveurs SSH et FTP.

L’installation d »es logiciels continue :

  1. Installation d’une application web pour accéder au Raspberry depuis un smartphone (PHP avec CodeIgniter) – Réalisée par mes soins ; cf chapitre « Application web pour contrôler le Raspberry » ci-dessous
  2. Changement de la politique de sécurité pour autoriser l’arret et reboot par un utilisateur quelconque (/usr/share/polkit-1/actions/org.freedesktop.login1.policy)
  3. Connexion automatique d’un user (pour ne pas avoir de mire de connexion)
  4. Ajout d’un script à la connexion pour lancer « xhost + » (pour que d’autres machines puissent ouvrir des fenêtres dans la session ouverte)
  5. Activation du dongle Wifi en mode AccessPoint (point d’accès Wifi) et paramétrage du DHCP

 

Application web pour contrôler le Raspberry

Cette application web permettra de piloter le Rasbberry depuis un smartphone. Elle est développée en PHP avec le Framework CodeIgniter. Un template HTML permet d’avoir une charte graphique en Responsive Design : http://binarycart.com/bclivedemos/01-05-2014/v1/bs-binary-admin/index.html

 

Fonctionnalités basiques de l’application PHP :

  • Etat du raspberry : charge machine, type de processeur, version du noyau, version et nom du système (Ubuntu)
  • Lancement de scripts SH (exemple : lancer une présentation avec un fichier PDF précis)
  • Parcours dans les répertoires
  • Caméra : prise de photo, enregistrement d’une vidéo
  • Arrêt et relance du raspberry

 

Utilisation avec un smartphone

Après avoir mis sous tension le raspberry, le smartphone peut s’y connecter par wifi. Un simple navigateur permet d’accéder aux fonctionnalités. Le smartphone devient une télécommande.

 

Copies d’écran sur smartphone

Page de connexion

Page d’accueil : description de la machine

Menu

Page des scripts à lancer

Page des médias USB connectés et détectés

Parcours des fichiers du Raspberry

Page de la gestion de la caméra : prendre une photo, prendre des vidéos

Page d’arrêt / relance du Raspberry