Station météo sur Arduino de A à Z. Partie 5

La fin. La partie précédente .


Table des matières:



Capteur extérieur. Logiciels


Parlez du logiciel pour le capteur d'outre-mer. Après cela, vous obtiendrez un système complet avec lequel vous pourrez déjà expérimenter.


Permettez-moi de vous rappeler que le serveur est une unité centrale à domicile qui peut communiquer avec Internet via le WiFi, et le client est un capteur prêt à l'emploi qui transmet les données au serveur par voie hertzienne.


Le code source du serveur et du client est ici .
Les textes sources sont accompagnés de commentaires détaillés.


Presque rien n'a besoin d'être configuré sur le client.


L'émetteur radio nRF24L01 +, plus précisément la bibliothèque RadioHead, nécessite la spécification des adresses serveur et client. Les adresses sont fournies si vous avez plusieurs serveurs et clients. Une adresse est n'importe quel entier. Lorsqu'un client envoie un paquet de données à un serveur, il indique à quel serveur ce paquet est destiné. Le serveur, connaissant à son tour sa propre adresse, détermine si ce paquet lui est destiné.


Par conséquent, SERVER_ADDRESS sur le serveur et sur le client doit être identique, mais CLIENT_ADDRESS pour différents clients doit être différent. En d'autres termes, si vous connectez un autre nouveau capteur à notre système à l'avenir, alors CLIENT_ADDRESS devra être modifié pour cela.


 //     #define SERVER_ADDRESS 10 #define CLIENT_ADDRESS 20 //     !!! 

Le RF_CHANNEL canal radio RF_CHANNEL doit être le même pour tout le monde. Par défaut, c'est 2. J'ai changé le numéro par défaut, vous pouvez en choisir un autre.


 //  .       #define RF_CHANNEL 73 

Les réglages du voltmètre pour mesurer la tension d'alimentation de la batterie doivent être modifiés:


 //   ,   const float r1 = 100400; // 100K const float r2 = 9960; // 10K //      //    http://localhost/arduino-secret-true-voltmeter/ const float typVbg = 1.082; //    1.0 -- 1.2  

Pour économiser de l'énergie, la bibliothèque légère de faible puissance pour Arduino est utilisée .


Voici mes mesures de consommation réelles pour l'Arduino Pro Mini avec cette lib:


  • gĂ©nĂ©ralement 25mA
  • lorsque vous travaillez avec DHT le mĂŞme
  • avec transmission radio 38 mA
  • Ă  LowPower.idle 15 mA
  • Ă  LowPower.powerdown 7,5 mA

Le client prend des mesures de température, d'humidité et de tension d'alimentation, regroupe tout cela dans une structure de données, envoie les données au serveur et «s'endort». Si des erreurs se sont produites pendant le transfert, le transfert est immédiatement répété.


Le serveur (central, unité d'origine), à ​​son tour, reçoit les données, confirme la réception et les traite.


Base de données, MySQL, PHP, serveur WWW


Après le travail effectué, nous avons une conception entièrement fonctionnelle de la station météo. Mais maintenant il y a un sou une douzaine de ces stations météorologiques, l'artisanat local n'est plus à la mode. Après tout, nous avons un Internet des objets.


Par conséquent, nous parlerons de la façon dont l'accès à ceux-ci est effectué sur votre Internet, nous y attacherons une base de données et une face Web à notre station météo.


L'énoncé du problème pour la "webcam":


  • recevoir et stocker les donnĂ©es de la station mĂ©tĂ©o: tempĂ©rature, humiditĂ©, pression atmosphĂ©rique, tension d'alimentation
  • afficher ces donnĂ©es
  • construire des graphiques.

Dans ce cas, nous avons besoin d'un hébergement avec prise en charge d'Apache, PHP et MySQL avec le module mysqli. Et ces conditions sont satisfaites par presque tous les hébergements de la planète Terre. Ou au lieu d'héberger, votre ordinateur jouera le rôle d'un serveur connecté à un routeur de réseau domestique et disposant d'un accès à Internet.


Création de base de données


Commençons par le tout début, à savoir avec la conception et la création de la base de données.


Les bases de données sont votre monde et vous pouvez l’étudier pendant longtemps. Nous allons donc brièvement aborder uniquement les éléments dont nous avons directement besoin.


Tous les scripts SQL se trouvent dans le répertoire weather-station/server/php-sql/


Où commence la conception de la base de données? Avec une représentation logique et physique.


Vue logique ou schéma de base de données:


  • Tableau de tempĂ©rature et d'humiditĂ© DHT
  • capteur de pression et de tempĂ©rature tableau de donnĂ©es BMP
  • les tables indiquĂ©es n'ont aucune relation entre elles, plus prĂ©cisĂ©ment, aucun lien n'est nĂ©cessaire.

Le schéma physique repose sur un SGBD et des types de données spécifiques. Il est plus facile de démonter avec un exemple spécifique. Le script SQL make_tables.sql les schémas logiques et physiques.


Chaque table doit avoir un champ type


 id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT 

Le nom du champ peut différer dans différentes bases de données, mais il n'y a qu'un sens: il s'agit d'un identifiant unique, une clé d'enregistrement. Pour l'avenir, si vous voyez une base de données dans des tables qui n'ont pas un tel compteur, vous devez savoir que cette base de données a été conçue par une personne très éloignée de la programmation, très probablement des sciences humaines.


Nous stockons les données des capteurs du même type dans une table; pour les capteurs d'un autre type, nous créons une autre table. Cela complique légèrement la base de données et la liaison PHP avec celle-ci, mais cela simplifie l'extension ou la modification de l'ensemble du système à l'avenir.


Il y a deux tableaux dans notre projet. La table arduino_dht stocke les données des capteurs de type DHT (température, humidité), la table arduino_bmp stocke les données des capteurs de type BMP (température, pression). Si à l'avenir vous souhaitez avoir, par exemple, un capteur de gaz ou un détecteur de mouvement, alors créez des tableaux supplémentaires, ne soyez pas paresseux. Si vous connectez un autre capteur de type DHT11 ou DHT22, vous n'avez pas besoin de créer une table supplémentaire, utilisez la table arduino_dht . J'espère que le principe est clair: une entité physique distincte est une table distincte.


Si les données de plusieurs capteurs du même type sont stockées dans un tableau, comment les distinguer? Pour ce faire, entrez un champ dans chaque table


 idSensor INTEGER 

En fait, c'est CLIENT_ADDRESS que nous avons enregistré dans le client/client.ino pour chaque instance du client-client distant et dans server/server.ino pour le capteur qui est connecté directement au serveur - l'unité centrale.


Dans les systèmes industriels, il devrait y avoir un autre tableau - la correspondance d' idSensor et sa description verbale et lisible par l'homme. Par exemple, un capteur avec idSensor = 2 est «Température, humidité dans l'appartement» , etc. Mais dans notre projet, nous ne compliquerons pas, rappelez-vous simplement que:


  • un capteur avec idSensor , il s'agit de CLIENT_ADDRESS , Ă©gal Ă  11 - c'est le capteur domestique sur le serveur - l'unitĂ© centrale,
  • un capteur avec idSensor , c'est aussi CLIENT_ADDRESS , Ă©gal Ă  20 - c'est le premier (dans notre projet et le seul) client de capteur basĂ© sur la fenĂŞtre.

Ensuite. Les tableaux stockent les données suivantes:


  • ipRemote - Adresse IP de la station mĂ©tĂ©o (serveur) d'oĂą proviennent les donnĂ©es, utile pour le dĂ©bogage et la surveillance,
  • dateCreate - date de la crĂ©ation de l'enregistrement,
  • millis - utile pour le dĂ©bogage, c'est le temps en millisecondes depuis le dĂ©but de l'esquisse sur l'Arduino,
  • tempĂ©rature - tempĂ©rature
  • humiditĂ© - humiditĂ©
  • tension - tension d'alimentation,
  • pression - pression
  • erreurs - le nombre d'erreurs (non utilisĂ©es). Il Ă©tait destinĂ© Ă  stocker le nombre d'erreurs de transmission, etc., afin que vous puissiez Ă©valuer Ă  distance l'Ă©tat de l'ensemble du système.

Comme vous pouvez le voir, les arduino_bmp arduino_dht et arduino_bmp très similaires, la différence ne concerne que les champs de pression et d'humidité, et il y a un désir de tout vider dans un tas (table). Mais la première forme normale n'ordonne pas de le faire, de nombreux programmeurs débutants ont essayé de contourner cela, mais aucun d'entre eux n'a réussi, et nous ne le ferons pas. Voilà comment ne pas remarquer la loi de la gravitation universelle, pour le moment elle pourrait bien se révéler.


La table arduino_error_log utile pour le débogage - c'est un journal des erreurs et autres messages système.


La création d'une base de données et de son utilisateur avec des droits est décrite dans make_db.sql


 -- .  config.php --   CREATE DATABASE IF NOT EXISTS db_weather; --   CREATE USER 'u_weather'@'localhost' IDENTIFIED BY '***PASSWORD***'; GRANT ALL ON db_weather.* TO 'u_weather'@'localhost'; 

Ceci est fait une fois, le nom et le nom d'utilisateur de la base de données peuvent venir avec le vôtre. Et ce qui doit être fait exactement, c'est de définir votre mot de passe.


PHP et serveur web


Tous les paramètres de l'interface Web sont stockés dans config.php . Modifiez-le en fonction des paramètres de votre base de données.


Définissez votre fuseau horaire au format PHP


 date_default_timezone_set('Europe/Prague'); 

Tous les fuseaux horaires disponibles sont décrits ici .


Définissez votre clé secrète pour l'accès (sous forme de nombre) qui doit correspondre à la constante SOURCE_KEY du sketch server.ino


 $access_key = '***KEY***'; 

Dans notre serveur Web, il n'y a pas d'autorisation, de saisie de mot de passe, cela compliquerait la conception entière. Pour un prototype, ce n'est pas nécessaire. Par conséquent, toute la protection repose sur le fichier robots.txt , l'absence d' index.php et cette clé secrète d'accès.


Le script PHP principal weather.php accepte une simple requête HTTP GET avec des données et les stocke dans les tables de base de données correspondantes. Si la clé $access_key ne correspond pas, la demande sera rejetée.


Le weather-view.php utilisé pour afficher les tableaux de données et contient des hyperliens vers d'autres scripts d'interface Web. Appelez-le comme ça


 http:// / /weather-view.php?k= access_key 

Par exemple


 http://yourhost/iot/weather-view.php?k=12345 

weather-view.php affiche des étiquettes simples où vous devez vous rappeler que:


  • le capteur avec l'identifiant 11 est le capteur domestique sur le serveur,
  • Le capteur avec id 20 est un capteur de fenĂŞtre.

Le script function.php contient des fonctions communes Ă  tous les scripts PHP.


Le chart-dht.php est responsable de la cartographie à l'aide de Google Charts . Voici, par exemple, un graphique de la tension d'alimentation du capteur étranger. La tension augmente lors d'une journée ensoleillée en raison de la batterie solaire, puis l'alimentation électrique des batteries se décharge progressivement.


Graphique


export-dht.php exporte les données des tables de base de données MySQL vers un fichier CSV. Pour une importation et une analyse supplémentaires dans des feuilles de calcul.


export-voltage.php exporte les données sur la tension d'alimentation du capteur de fenêtre de la base de données MySQL vers un fichier CSV. Utile pour le débogage.


truncate.php efface toutes les tables, c'est-à-dire supprime toutes nos données. Utile pour le débogage. Il n'y a pas de lien vers ce script depuis weather-view.php , vous devez donc l'appeler via un lien direct dans la barre d'adresse de votre navigateur avec $access_key .


Lors de la réception de données, la fonction mysqli_real_escape_string() est couramment utilisée pour empêcher des valeurs incorrectes d'entrer dans la base de données.


N'oubliez pas de mettre robots.txt à la racine de votre site pour l'empêcher de pénétrer dans les moteurs de recherche.


ESP8266, WiFi et transfert de données


Et maintenant, revenons à l'esquisse server.ino , à la partie qui se connecte au point d'accès WiFi et envoie des données au serveur Web.


Comme je l'ai déjà écrit, je ne pouvais pas trouver une bibliothèque normale pour Arduino pour contrôler le module ESP8266 à l'aide des commandes AT, j'ai dû me "regrouper". Permettez-moi également de vous rappeler que vous devez flasher une version spécifique du firmware dans ESP8266-01. Et maintenant, quand tout est prêt, voyons comment cela fonctionne.


Pour accéder au serveur Web dans l'esquisse server.ino , server.ino devez modifier ces constantes


 const String DEST_HOST = " "; //  habr.com const String DEST_PORT = " "; //  80 const String DEST_URL = "/ /weather.php"; const String SOURCE_KEY= "  "; //    $access_key  config.php 

Dans server.ino dans la fonction void setup() , l'ESP8266 passe d'abord en mode Station, c'est-Ă -dire il commence Ă  fonctionner en tant que client WiFi


 espSendCmd(«AT+CWMODE_CUR=1», «OK», 3000); 

puis suit la connexion au point d'accès


 espState = espConnectToWiFi(); 

Si la connexion ne se produit pas, la tentative est répétée (une fois)


 if ( espState != ESP_SUCCESS ) { delay(5000); Serial.println("WiFi not connected! Try again ..."); espConnectToWiFi(); } 

Sélectionnez ensuite le mode de connexion unique TCP / IP


 espSendCmd("AT+CIPMUX=0", "OK", 2000); 

Lors de l'envoi de données de capteurs de type DHT au serveur Web, une fonction est utilisée qui indique le type=dht données comme type=dht


 espSendData( "type=dht&t=" + String(dhtData.temperature) + "&h=" + String(dhtData.humidity) + "&v=" + String(dhtData.voltage) + "&s=" + String(CLIENT_ADDRESS) ); 

Lors de l'envoi de données de capteurs BMP vers un serveur Web, la même fonction est utilisée avec le type de données indiqué par type=bmp


 espSendData( "type=bmp&t=" + String(temperature_bmp) + "&p=" + String(pressure_bmp) + "&s=" + String(CLIENT_ADDRESS) ); 

La fonction espSendData() accepte une chaîne de requête HTTP GET et l'envoie au serveur Web comme prévu.


À l'intérieur de lui-même, espSendData() vérifie la disponibilité du module ESP en lui envoyant la commande «AT», puis il vérifie la connexion WiFi et se reconnecte si nécessaire. Ensuite, les données sont envoyées et la connexion TCP est fermée.


Application Android


De nos jours, quand tout le monde peut clignoter une LED, vous ne surprendrez personne avec une station météo. Mais si l'engin sait communiquer avec le serveur via le WiFi, a un visage web et une application mobile, alors c'est quelque chose! Par serveur, nous entendons ici bien sûr le serveur d'applications, c'est-à-dire dans notre cas, il s'agit d'une liaison PHP et d'un SGBD MySQL. Il n'y a pas assez de cerises sur le gâteau, à savoir l'application Android, que nous allons écrire maintenant.


L'architecture


L'architecture de l'ensemble de la plateforme logicielle de station météo est simple:


  • la partie serveur (unitĂ© centrale) de la station mĂ©tĂ©o collecte les donnĂ©es des clients capteurs Ă  distance
  • puis il transfère des donnĂ©es au serveur Web d'applications, qui enregistre ces donnĂ©es dans la base de donnĂ©es
  • L'application Android (ou toute autre application distante: iOS, navigateur) demande des donnĂ©es Ă  un serveur Web et les affiche Ă  l'Ă©cran.

Sur l'écran de l'appareil Android, nous afficherons les lectures de capteur actuelles et les plus récentes.


HTTP GET et JSON


La question qui doit être résolue en premier lieu est de savoir comment les données seront transférées du serveur Web vers l'application Android.


Il n'est pas nécessaire d'inventer quoi que ce soit ici, tout a déjà été inventé pour nous - ce sont HTTP GET et JSON.


Dans notre cas, une simple demande GET au serveur Web peut être compilée et déboguée manuellement alors que l'application Android n'est pas encore prête.


En Java et Android, il existe des bibliothèques prêtes à l'emploi pour le traitement des données au format JSON. JSON est un format de texte lisible par l'homme, utile pour le débogage.


Afin de générer des données actuelles à partir des capteurs des stations météorologiques, créez un nouveau script PHP last-data-to-json.php sur le serveur Web.


Appel de script:


 http://<>/last-data-to-json.php?k=<access_key> 

où <access_key> , comme nous nous en souvenons, est la clé d'accès secrète à la base de données.


Exemple de réponse au format JSON:


 { "DHT 11":{ "idSensor":"11", "dateCreate":"2016-04-20 18:06:03", "temperature":"19", "humidity":"26", "voltage":"5.01" }, "DHT 20":{ "idSensor":"20", "dateCreate":"2016-04-18 07:36:26", "temperature":"10", "humidity":"26", "voltage":"3.7" }, "BMP 11":{ "idSensor":"11", "dateCreate":"2016-04-20 18:06:22", "temperature":"19", "pressure":"987.97" } } 

Il faut rappeler que nous avons 3 capteurs. Leur ID et leur type (DHT ou BMP) sont codés en dur dans tout le code de la station météo. Cette méthode de codage hardcore est idéologiquement incorrecte, mais pour un prototype dessiné au genou (où une solution rapide et facile est nécessaire), c'est un compromis raisonnable.


 $idSensor = 11; //  DHT  $idSensor = 11; //  BMP  $idSensor = 20; //  DHT  

Le last-data-to-json.php prend les dernières données de ces capteurs hétérogènes de la base de données et les emballe au format JSON. La sélection des données de la base de données «de bout en bout» se déroule ainsi:


 SELECT <> FROM <> ORDER BY id DESC LIMIT 1; 

Android


Nous allons maintenant écrire une application Android simple qui demande, reçoit, décode les données JSON et affiche des informations à l'écran.


Notre application Android sera aussi simple que possible, seule l'essence de la technologie. Plus loin autour de ce "squelette" il sera déjà possible de remonter différentes "beautés".


Voici une capture d'écran de ce qui devrait se traduire par


Android


Comme vous pouvez le voir, l'interface utilisateur est juste Spartan, basée sur LinearLayout, rien de plus.


En haut de TextView, l'ID des capteurs et leurs données météorologiques sont affichés. Le bouton Actualiser lance une deuxième demande au serveur Web. Ensuite dans EditText est le seul paramètre de programme - c'est l'URL de demande dans le formulaire


 http://< >/last-data-to-json.php?k=<access_key> 

Que faut-il noter?


Dans le manifeste, ajoutez des lignes autorisant Internet et vérifiant l'état de la connexion réseau:


 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> 

Travailler avec le réseau et recevoir des données du site Web est le suivant.


Nous utilisons AsyncTask pour créer une tâche d'arrière-plan distincte du thread d'interface utilisateur principal. Cette tâche en arrière-plan prend l'URL de la demande et l'utilise pour créer la HttpURLConnection .


Une fois la connexion établie, AsyncTask charge le contenu de la page Web (JSON) en tant que InputStream. Ensuite, InputStream est converti en chaîne, qui est décodée à l'aide de JSONObject et affichée dans l'interface utilisateur à l'aide de la méthode onPostExecute() .


Dans MainActivity.java, modifiez l'URL de votre:


 private static final String defUrl = "http://host/dir/last-data-to-json.php?k=< >"; 

il sera utilisé par défaut la première fois que vous exécuterez une application Android.


Épilogue


Eh bien, quelque chose a déjà fonctionné. Ensuite, vous pouvez optimiser quelque chose, remplacer quelque chose, vous pouvez tout jeter, mais aussi emprunter quelque chose.


Un autre point sensible distinct est la consommation d'énergie . Je recommande de lire les commentaires sur les articles où il existe de nombreux conseils pratiques.


Ă€ l'infini ... et au-delĂ .

Source: https://habr.com/ru/post/fr426019/


All Articles