Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Système écologique Herb Box

Composants et fournitures

Amazon Alexa Echo Dot
× 1
Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Arduino Proto Shield
× 1
Bouclier de relais Arduino 4
× 1
Pompe Aqua
× 2
Lampe de culture de plantes
× 1
Adaptateur d'alimentation CC 220 V
× 1
Adaptateur d'alimentation 12 V CC
× 1
Prise d'alimentation USB + câble
× 1
Tuyau d'air
× 1
Câbles de raccordement (générique)
× 1

Applications et services en ligne

Arduino IDE
Kit de compétences Amazon Alexa Alexa
Amazon Web Services AWS Lambda
Serveur Web php

À propos de ce projet

Comme mes plantes souffrent toujours de trop ou moins d'eau et que j'aime mettre beaucoup d'herbes dans ma vaisselle, j'ai décidé de créer un système d'irrigation sur mesure. La boîte pour mes herbes devrait être configurable et fonctionner automatiquement ou manuellement. Par conséquent, une interface vers un site Web existe pour permettre une configuration et afficher l'humidité dans un joli graphique. La dernière étape a été l'intégration de la commande vocale pour demander à Amazon Alexa l'humidité, allumer/éteindre une lampe de culture de plantes et démarrer l'irrigation, si l'automatisation est désactivée. Cliquez ici pour trouver le résultat.

J'ai commencé par la partie technique du projet et j'ai acheté un Arduino. Après quelques tutoriels, j'étais ferme avec le logiciel et le contrôle de l'Arduino. J'ai commandé un contrôleur wifi, des capteurs d'humidité, des pompes, une lampe de culture de plantes et du matériel supplémentaire requis (bouclier de relais pour séparer les circuits de la lampe et des pompes de l'Arduino, des fils et du bois de hêtre pour le cadre). Le code Arduino du résultat est fourni dans ce tutoriel, à côté de quelques informations sur la façon d'utiliser les composants dans vos projets. Le code site/api n'est pas fourni (sauf si la demande est très forte;) ).

Première étape :capteur d'humidité

La première étape a été de lire l'humidité avec mon Arduino. Le capteur d'humidité YL-69 était facile à connecter avec l'Arduino. Vous devez connecter la broche VCC à une broche GPIO (dans mon exemple la broche 06), la masse à la masse et l'A0 à une broche analogique (dans mon exemple la broche A1) de l'Arduino.

Tutoriel :Capteur d'humidité du sol

byte vccPin =6;byte dataPin =A1;void setup() { pinMode(vccPin, OUTPUT); digitalWrite(vccPin, LOW); Serial.begin(9600); while (!Serial);}int readHumidity() { digitalWrite(vccPin, HIGH); retard (500); // vous devez tester combien de temps vous pré-alimentez avant la mesure int value =analogRead(dataPin); digitalWrite(vccPin, LOW); return 1023 - value;}void loop() { Serial.print("HumidityLevel (0-1023):"); Serial.println(readHumidity()); retard (10000);} 

Deuxième étape :relais pour les pompes et la lampe

L'objectif suivant était d'installer un blindage de relais (4 relais) pour séparer les circuits de la lampe, des pompes et de l'Arduino. L'Arduino fonctionne sur 5V, les pompes utilisent 12V et la lampe de culture 230V. Le blindage doit être connecté aux broches 5V et de terre de l'Arduino. Chaque relais a en outre besoin d'une broche GPIO de votre choix pour s'allumer et s'éteindre. Enfin, vous pouvez utiliser un cavalier pour VCC JC à VCC sur le bouclier, ou utiliser une batterie supplémentaire (ce qui serait le mieux, mais je n'ai pas encore de batterie dans mon projet).

Il est important de comprendre que mon bouclier s'allume avec "LOW" sur la broche. Dès que ma broche est définie comme SORTIE, elle passe automatiquement à active. Dans le code, vous devez toujours basculer sur INPUT et LOW, si vous souhaitez que le relais soit désactivé. Par défaut, les broches Arduino sont INPUT et LOW.

Tutoriel :Bouclier de relais

Information :Pourquoi relais OUTPUT + LOW =Actif ?

byte pump1 =11;byte pump2 =10;void setup() { Serial.begin(9600); tandis que (!Série); pinMode(pompe1, SORTIE); // variante low/high digitalWrite(pump2, LOW); // entrée/sortie variante}boucle vide() { digitalWrite(pump1, HIGH); // pump1 désactivé pinMode(pump2, INPUT); // pump2 désactivé delay(1000); digitalWrite(pompe1, LOW); // pump1 activé pinMode(pump2, OUTPUT); // délai d'activation de la pompe2 (1000);} 

Troisième étape :Wi-Fi avec ESP-01

La connexion de l'espressif ESP8266 ESP-01 à l'Arduino pour le WiFi a été la partie la plus difficile. Il m'a fallu des heures pour faire fonctionner le wifi dans mon script.

L'ESP est connecté à :VCC =3.3V, GND =GND, CH_PD =3.3V, TX =Pin 02, RX =Pin 03. Pour une utilisation productive, vous devez utiliser au moins un convertisseur de niveau de 5V à 3.3V pour la broche 02 et la broche 03 aussi. Dans mon cas, cela a bien fonctionné.

Semblable à l'Arduino, l'ESP-01 est un autre microcontrôleur. Si vous voulez que les deux contrôleurs communiquent, vous devez utiliser la communication série. L'Arduino UNO utilise par défaut les broches 01 et 02 pour RX et TX. Mais ils sont également utilisés pour le débogage USB et il est donc suggéré d'inclure SoftwareSerial.h et de définir des broches personnalisées.

#include SoftwareSerial espSerial(3,2) ; // RX, TXvoid setup() { Serial.begin (9600); espSerial.begin(115200); // passer à 9600 après AT+UART_DEF=9600,8,1,0,0 while (!Serial);}void loop() { if (espSerial.available()) { Serial.write(espSerial.read()); } if (Serial.available()) { espSerial.write(Serial.read()); }} 

En exécutant le script ci-dessus, vous pouvez entrer des commandes AT dans le moniteur série et voir les résultats. La communication série est sujette à l'échec, j'ai donc diminué le débit en bauds de communication utilisé par l'ESP de 115200 à 9600.

Tutoriel :ESP8266 + Arduino | Tutoriel :ESP8266 général (allemand)

  • Une classe d'aide utile (mais utilise trop de mémoire) :Bibliothèque :WiFiEsp
  • Outil de vérification de la mémoire :Bibliothèque :MemoryFree

Le script utilise HTTP 1.0, car avec HTTP 1.1, les octets font partie de la réponse. Il est important de faire attention aux sauts de ligne pour que la commande soit envoyée après AT+CIPSEND. S'ils sont erronés, vous recevrez une erreur d'envoi d'octet.

#include SoftwareSerial espSerial(3,2) ; // RX, TXconst char* ssid ="";const char* pass ="";void setup() { Serial.begin(9600); espSerial.begin(9600); while(!Série); while(!connectToWiFi()); // demande le site Web et imprime le résultat if (httpRequest("my.server.com", "/site/subsite/index.php")) { while (espSerial.available()) { Serial.write(espSerial.read() ); } }}void loop() { // s'exécute encore et encore if (espSerial.available()) { Serial.write(espSerial.read()); } if (Serial.available()) { espSerial.write(Serial.read()); }}bool connectToWiFi() { delay(2000;) espSerial.setTimeout(3000); while (espSerial.available()) Serial.write(espSerial.read()); Serial.println(F("[ESP] Connexion au WiFi")); espSerial.println(F("AT+CIPSTATUS=2")); if (!espSerial.find("OK")) { espSerial.setTimeout (10000); Serial.println(F("[ESP] Reset Module")); espSerial.println(F("AT+RST")); if (!espSerial.find("ready")) { Serial.println(F("[ESP] La réinitialisation a échoué")); renvoie faux ; } Serial.println(F("[ESP] Définir CWMode")); espSerial.println(F("AT+CWMODE=1")); if (!espSerial.find("OK")) { Serial.println(F("[ESP] Mode a échoué")); renvoie faux ; } Serial.println(F("[ESP] Se connecter au routeur")); espSerial.print(F("AT+CWJAP=\"")); espSerial.print(ssid); espSerial.print(F("\",\"")); espSerial.print(pass); espSerial.println ("\""); if (!espSerial.find("OK")) { Serial.println(F("[ESP] La connexion WiFi a échoué")); renvoie faux ; } } espSerial.setTimeout(3000); Serial.println(F("[ESP] WiFi est connecté")); return true;}bool httpRequest(String server, String site) { String cmd =""; cmd +="GET " + site + " HTTP/1.0\r\n" ; cmd +="Hôte :" + serveur + "\r\n" ; cmd +="Connexion :fermer" ; int cmdLength =cmd.length() + 4; // Serial.println(cmd); espSerial.print(F("AT+CIPSTART=\"TCP\",\"")); espSerial.print(serveur); espSerial.println(F("\",80")); if (!espSerial.find("OK")) { Serial.println(F("[ESP] Erreur de connexion TCP")); renvoie faux ; } espSerial.print(F("AT+CIPSEND=")); espSerial.println(cmdLength); if (!espSerial.find(findGT)) { Serial.println(F("[ESP] Send State Error")); renvoie faux ; } espSerial.print(F("GET ")); espSerial.print(site); espSerial.print(F(" HTTP/1.0\r\n")); espSerial.print(F("Hôte :")); espSerial.print(serveur); espSerial.print(F("\r\n")); espSerial.print(F("Connexion :fermer\r\n")); espSerial.println(); if (!espSerial.find(":")) { Serial.println(F("Octets non envoyés")); espSerial.print(F("AT+CIPCLOSE")); renvoie faux ; } car status[32] ={0}; espSerial.readBytesUntil('\r', status, sizeof(status)); if (strcmp(status, "HTTP/1.1 200 OK") !=0) { Serial.print(F("[ESP] Réponse inattendue :")); Serial.println(statut); renvoie faux ; } if (!espSerial.find("\r\n\r\n")) { Serial.println(F("[ESP] Réponse invalide")); renvoie faux ; } // Ignorer les en-têtes HTTP // if (!espSerial.find(\r\n)) { Serial.println(F("[ESP] Octets non trouvés")); retourner; } // saute des octets (pour http 1.1) renvoie true;i} 

Quatrième étape :la boîte en bois

Le cadre était prévu pour ranger tous les appareils électroniques et trois pots d'herbes du supermarché. J'ai mesuré les tailles de tous les composants et structuré les positions. Quatre capteurs d'humidité, deux pompes, le blindage Arduino +, un blindage de relais 4x et une prise USB et certains fils doivent tenir dans la boîte. Il a été fabriqué en bois de hêtre, pour le rendre solide et résistant aux gouttes d'eau sans glaçure supplémentaire.

Les cercles ont été sciés avec une scie sauteuse sur une table de scie sauteuse faite maison. Les supports végétaux sont collés à l'intérieur des cercles avec de la colle chaude. Les côtés de la boîte sont collés par de la colle à bois (D3 pour la résistance à l'eau). A part l'électronique, je n'ai utilisé ni vis ni clous à côté de la fixation du panneau inférieur.

J'ai mis tous les circuits, fils et tubes d'eau à l'intérieur de la boîte, j'ai retiré les capteurs et les tubes pour le réservoir d'eau supplémentaire. Avant de refermer la boite, j'ai ajouté des soucoupes pour éviter que l'eau ne se noie à l'intérieur de la boite pour protéger l'électronique.

Cinquième étape :l'API du site Web

L'API et le site Web sont basés sur jQuery, Bootstrap, X-editable (pour les formulaires ajax en ligne) et Chart.js (pour le graphique d'humidité), codés en php. Sur le site Web, vous pouvez définir les paramètres de l'Arduino (par exemple, les broches du capteur, l'intervalle de vérification de l'humidité, les pompes par plante, les broches VCC de la pompe, la broche VCC légère) et trouver l'humidité actuelle + le graphique.

La configuration est fournie par JSON pour l'Arduino. Après le démarrage et à intervalles fréquents, la boîte à herbes vérifie les nouveaux paramètres. Pour analyser le JSON avec l'Arduino, j'ai utilisé la bibliothèque ArduinoJson. Pour l'intervalle d'interrogation, j'ai utilisé StensTimer.

Bibliothèque :ArduinoJson | Bibliothèque :StensTimer

Sixième étape :Intégration Alexa

Le site Web fournit une API pour la communication Alexa. Il sert de hub pour recevoir la demande JSON par Alexa et la traduit en un JSON personnalisé utilisé par l'Arduino (par exemple, lampe allumée, irriguer l'usine 1, ...). L'Arduino recherche de nouvelles actions et les exécute.

Parce que les demandes vocales sont plus que simplement activées/désactivées, j'ai implémenté une compétence Alexa et pas Alexa Smart Home. AWS Lampda transmet la requête JSON à mon API, qui analyse les intentions.

var https =require('https');exports.handler =(événement, contexte, rappel) => { var postData =JSON.stringify(événement); var options ={ hôte :'', chemin :'', port :443, méthode :'POST', en-têtes :{ 'Content-Type' :'application/json' , 'Content-Length' :postData.length, } } ; // configurer la requête var postRequest =https.request(options, function(res) { res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('Response:' + chunk); // console.log(chunk); callback(null, JSON.parse(chunk)); }); }); // publier les données postRequest.write(postData); postRequest.end();}; 

Un extrait des intentions que j'ai utilisées par ma compétence :

  • ReadHumidityIntent Comment vont mes plantes
  • ReadHumidityIntent Comment va mon {plantName}
  • IrrigatePlantIntent Irriguer mes plantes
  • IrrigatePlantIntent Irriguer mon {plantName} pendant {durationSeconds} secondes
  • SwitchIntent Changer la lampe {switchState}
  • ReadIrrigateIntent Quelles plantes ont besoin d'eau
  • ReadLastIrrigationIntent À quand remonte la dernière irrigation de mon {plantName}

Enfin, j'ai ajouté la prise en charge des paramètres régionaux pour l'utilisation de l'allemand et de l'anglais.

Le résultat

En conséquence, j'ai une boîte en bois pour mettre des pots d'herbes de supermarché, prendre des tubes d'eau et des capteurs d'humidité dans le sol et les tubes dans un réservoir d'eau externe. Avec l'intégration Alexa, je peux dire les phrases suivantes :

  • "Alexa, demande à Herb Box comment sont mes plantes " - Réponse :" L'usine 1 va bien, l'usine 2 est sèche, ..."
  • "Alexa, dis à Herb Box d'irriguer mon basilic pendant 5 secondes " - Réponse :" Irriguer le basilic pendant 5 secondes "
  • "Alexa, demande à la boîte à herbes quelles plantes ont besoin d'être irriguées " - Réponse :" L'usine 1 est sèche, l'usine 3 est sèche, ..."
  • "Alexa, demande à la boîte à herbes à quand remonte la dernière irrigation de mon basilic " - Réponse :"La dernière irrigation du basilic remonte à 36 h"
  • "Alexa, dis à Herb Box d'allumer la lampe " - Réponse : « Lampe de culture des plantes allumée »

Demander à Alexa l'humidité de ma plante et l'irriguer ensuite (allemand) :

Demander à Alexa d'allumer la lampe de culture des plantes :

GIF montrant le résultat sans les vidéos :

Fonctionnalités prévues

Les fonctionnalités suivantes ne sont pas encore implémentées mais prévues pour le futur :

  • Mode d'économie d'énergie pour le code source Arduino
  • Ajoutez des Arduino Nanos externes avec communication sans fil (2,4 GHz) pour mesurer l'humidité d'autres plantes dans la maison (le boîtier est le hub pour le WiFi) - en utilisant uniquement des piles
  • Étendre l'API pour plusieurs instances de la boîte d'herbes, pour les amis (et qui que ce soit, si cela vous intéresse ? !)
  • Ajouter un bouton pour irriguer et allumer la lampe sur la box sans site internet ni Alexa
  • Images Alexa (carte dans la réponse de compétence)

Mise à jour 23.03.2018

J'ai ajouté deux nouvelles intentions. L'un d'eux est important pour la fonctionnalité prévue des Adruino Nanos externes qui enregistrent simplement l'humidité.

  • Quelles plantes sont sèches
  • À quand remonte la dernière irrigation

Code

  • EcoActionBuffer.h
  • EcoActionBuffer.cpp
  • Plant.cpp
  • Plant.h
  • WhiteWalnut.ino
  • WhiteWalnutApi.cpp
  • WhiteWalnutApi.h
EcoActionBuffer.hArduino
#ifndef ECOACTIONBUFFER_H#define ECOACTIONBUFFER_H#include "Arduino.h"#include "StensTimer.h"struct EcoActionBuffer :public IStensTimerListener { long entryNo; action internationale ; broche int; longue durée; void timerCallback(Timer* timer); void switchPin(int pin, valeur booléenne); void readStack(); processus vide (); void toSerial(); void reset();};#endif
EcoActionBuffer.cppArduino
#include "EcoActionBuffer.h"#include "StensTimer.h"#include "WhiteWalnutApi.h"#define ACTION_ECOACTION_READ 1#define ACTION_ECOACTION_HIGH 2#define ACTION_ECOACTION_LOW 3void EcoActionBuffer::readStack() { reset(); WhiteWalnutApi::receiveActionFromStack(*this); if (entryNo !=0) { process(); // WhiteWalnutApi::updateActionOnStack(*this); // désactivé pour les performances }}void EcoActionBuffer::process() { toSerial(); pinMode(broche, SORTIE); digitalWrite(broche, HAUT); switch (action) { case ACTION_ECOACTION_HIGH:switchPin(pin, true); Pause; case ACTION_ECOACTION_LOW : switchPin(pin, false); Pause; } if (duration !=0) { StensTimer::getInstance()->setTimer(this, -pin, duration); }}void EcoActionBuffer::timerCallback(Timer* timer) { switch (timer->getAction()) { case ACTION_ECOACTION_READ:readStack(); Pause; } if (timer->getAction() <0) { switchPin(abs(timer->getAction()), false); }}void EcoActionBuffer::switchPin(int pin, valeur booléenne) { switch (value) { case true:digitalWrite(pin, LOW); Pause; case false : digitalWrite(pin, HIGH ); Pause; } WhiteWalnutApi::switchPin(pin, value);}void EcoActionBuffer::reset() { entryNo =0; action =0 ; broche =0 ; duration =0;}void EcoActionBuffer::toSerial() { Serial.print(entryNo); Serial.print(F(" - Action :")); Serial.print(action); Serial.print(F(", Pin:")); Serial.print(pin); Serial.print(F(", Durée :")); Serial.print(durée); Serial.println();}
Plant.cppArduino
#include "Plant.h"#include "StensTimer.h"#include "WhiteWalnutApi.h"#define ACTION_PLANT_CHECKHUMIDITY 2#define PIN_HUMIDITY_VCC 12void Plant::checkHumidity() { if (humidityDataPin !=0) { Serial.print (code); Serial.print(F(" - Vérifier l'humidité...")); digitalWrite(PIN_HUMIDITY_VCC, HAUT); retard (200); // TODO int humidité =1023 - analogRead(humidityDataPin); digitalWrite(PIN_HUMIDITY_VCC, LOW); Serial.println(humidité); WhiteWalnutApi::sendHumidity(*this, humidité); if (humidityCheckInterval ==0) humidityCheckInterval =60000; StensTimer::getInstance()->setTimer(this, ACTION_PLANT_CHECKHUMIDITY, humidityCheckInterval); } else StensTimer::getInstance()->setTimer(this, ACTION_PLANT_CHECKHUMIDITY, 60000);}void Plant::updateApi() { WhiteWalnutApi::updatePlant(*this); // WhiteWalnutApi::sendHeartbeat(*this); // désactivé pour les performances pinMode(PIN_HUMIDITY_VCC, OUTPUT); toSerial();}void Plant::timerCallback(Timer* timer) { switch (timer->getAction()) { case ACTION_PLANT_CHECKHUMIDITY:checkHumidity(); Pause; }}void Plant::toSerial() { Serial.print(code); Serial.print(F(" - DataPin:")); Serial.print(humiditéDataPin); Serial.print(F(", Interval:")); Serial.print(humiditéCheckInterval); Serial.println();}
Plant.hArduino
#ifndef PLANT_H#define PLANT_H#include "Arduino.h"#include "StensTimer.h"struct Plant :public IStensTimerListener { const char* code; int humiditéDataPin; longue humiditéCheckInterval; void checkHumidity(); void timerCallback(Timer* timer); void toSerial(); void updateApi();};#endif
WhiteWalnut.inoArduino
#include "EcoActionBuffer.h"#include "Plant.h"#include "StensTimer.h"#include "WhiteWalnutApi.h"struct TimerHelper :public IStensTimerListener { public:void updateApi(); void timerCallback(Timer* timer);};StensTimer* stensTimer;TimerHelper apiTimer;Plant leftPlant;Plant centerPlant;Plant rightPlant;Plant externalPlant;EcoActionBuffer actionBuffer;#define ACTION_PLANT_UPDATE 1#define ACTION_voidbegin() Serial_READ 1; tandis que (!Série); stensTimer =StensTimer::getInstance(); leftPlant.code ="GAUCHE"; centerPlant.code ="CENTRE"; rightPlant.code ="RIGHT"; externalPlant.code ="EXTERNE"; while(!WhiteWalnutApi::connectToWiFi()) delay(2000); WhiteWalnutApi::switchPin(0, false); apiTimer.updateApi(); leftPlant.checkHumidity(); centerPlant.checkHumidity(); rightPlant.checkHumidity(); externalPlant.checkHumidity(); actionBuffer.readStack(); StensTimer::getInstance()->setInterval(&apiTimer, ACTION_PLANT_UPDATE, 60000); StensTimer::getInstance()->setInterval(&actionBuffer, ACTION_ECOACTION_READ, 1000);}void loop() { stensTimer->run();}void TimerHelper::updateApi() { leftPlant.updateApi(); centerPlant.updateApi(); rightPlant.updateApi(); externalPlant.updateApi();}void TimerHelper::timerCallback(Timer* timer){ switch (timer->getAction()) { case ACTION_PLANT_UPDATE:updateApi(); Pause; }}
WhiteWalnutApi.cppArduino
vous devez ajouter vos paramètres WiFi et API
#include "Arduino.h"#include "ArduinoJson.h"#include "EcoActionBuffer.h"#include "MemoryFree.h"#include "Plant.h"#include " SoftwareSerial.h"#include "WhiteWalnutApi.h"SoftwareSerial espSerial(3, 2);const char* ssid ="";const char* pass ="";const char* API_SERVER ="";const char* API_PLANT ="";const char* API_ACTION ="";char* findOK ="OK";char* findRY ="ready";char* findGT =">";char* findDP =":";char* findHD ="\r\n\r\n";char* findBT ="\r\n"; bool WhiteWalnutApi::connectToWiFi() { espSerial.begin(9600); espSerial.setTimeout(3000); while (espSerial.available()) Serial.write(espSerial.read()); Serial.println(F("[ESP] Connexion au WiFi")); espSerial.println(F("AT+CIPSTATUS=2")); if (!espSerial.find(findOK)) { espSerial.setTimeout (10000); Serial.println(F("[ESP] Reset Module")); espSerial.println(F("AT+RST")); if (!espSerial.find(findRY)) { Serial.println(F("[ESP] La réinitialisation a échoué")); renvoie faux ; } Serial.println(F("[ESP] Définir CWMode")); espSerial.println(F("AT+CWMODE=1")); if (!espSerial.find(findOK)) { Serial.println(F("[ESP] Mode a échoué")); renvoie faux ; } Serial.println(F("[ESP] Se connecter au routeur")); espSerial.print(F("AT+CWJAP=\"")); espSerial.print(ssid); espSerial.print(F("\",\"")); espSerial.print(pass); espSerial.println ("\""); if (!espSerial.find(findOK)) { Serial.println(F("[ESP] La connexion WiFi a échoué")); renvoie faux ; } } espSerial.setTimeout(3000); Serial.println(F("[ESP] WiFi est connecté")); return true;}void WhiteWalnutApi::updatePlant(Plant&plant) { String site =String(API_PLANT) + "?action=get&code=" + String(plant.code); while (!httpRequest(site)) connectToWiFi(); JsonObject&root =parseJson(); if (root.success()) { plant.humidityDataPin =root["dataPin"].as(); plant.humidityCheckInterval =atol(root["interval"].as()); }}void WhiteWalnutApi::sendHumidity(Plant&plant, humidité int) { String site =String(API_PLANT) + "?action=humidity&code=" + String(plant.code) + "&humidity=" + String(humidity); while (!httpRequest(site)) connectToWiFi(); // TODO:SUPPRIMER LE RETOUR}void WhiteWalnutApi::sendHeartbeat(Plant&plant) { String site =String(API_PLANT) + "?action=heartbeat&code=" + String(plant.code); while (!httpRequest(site)) connectToWiFi();}void WhiteWalnutApi::receiveActionFromStack(EcoActionBuffer&actionBuffer) { while (!httpRequest(String(API_ACTION))) connectToWiFi(); JsonObject&root =parseJson(); if (root.success()) { actionBuffer.entryNo =atol(root["entryNo"].as()); actionBuffer.action =root["actionEnum"].as(); actionBuffer.pin =root["pin"].as(); actionBuffer.duration =atol(root["value"].as()); }}void WhiteWalnutApi::updateActionOnStack(EcoActionBuffer&actionBuffer) { String site =String(API_ACTION) + "?action=processed&entryNo=" + String(actionBuffer.entryNo); while (!httpRequest(site)) connectToWiFi();}void WhiteWalnutApi::switchPin(int pin, bool value) { String site =String(API_ACTION) + "?action=switch&pin=" + String(pin) + "&value=" + Chaîne(valeur); while (!httpRequest(site)) connectToWiFi();}bool WhiteWalnutApi::httpRequest(String site) { // char* cmd; // sprintf(cmd, "GET %s HTTP/1.0\r\nHost :%s\r\nConnection :close", site, API_SERVER); /* Chaîne cmd =""; cmd +="GET " + site + " HTTP/1.0\r\n" ; cmd +="Hôte :" + Chaîne(API_SERVER) + "\r\n" ; cmd +="Connexion :fermer" ; int cmdLength =cmd.length() + 4; Serial.println(cmd); */ int cmdLength =44 + site.length() + strlen(API_SERVER); // Serial.print(F("[MEMORY] ")); // Serial.print(freeMemory()); // Serial.print(F(" - ")); // Serial.println(site); // -> 785 for external espSerial.print(F("AT+CIPSTART=\"TCP\",\"")); espSerial.print(API_SERVER); espSerial.println(F("\",80")); if (!espSerial.find(findOK)) { Serial.println(F("[ESP] TCP Connection Error")); renvoie faux ; } espSerial.print(F("AT+CIPSEND=")); espSerial.println(cmdLength); // espSerial.println(strlen(cmd)); if (!espSerial.find(findGT)) { Serial.println(F("[ESP] Send State Error")); renvoie faux ; } espSerial.print(F("GET ")); espSerial.print(site); espSerial.print(F(" HTTP/1.0\r\n")); espSerial.print(F("Host:")); espSerial.print(API_SERVER); espSerial.print(F("\r\n")); espSerial.print(F("Connection:close\r\n")); espSerial.println(); // while (espSerial.available()) Serial.println(espSerial.readString()); retourner; if (!espSerial.find(findDP)) { Serial.println(F("Bytes not sent")); espSerial.print(F("AT+CIPCLOSE")); renvoie faux ; } char status[32] ={0}; espSerial.readBytesUntil('\r', status, sizeof(status)); if (strcmp(status, "HTTP/1.1 200 OK") !=0) { Serial.print(F("[ESP] Unexpected response:")); Serial.println(status); renvoie faux ; } // Check HTTP status if (!espSerial.find(findHD)) { Serial.println(F("[ESP] Invalid response")); renvoie faux ; } // Skip HTTP headers // if (!espSerial.find(findBT)) { Serial.println(F("[ESP] Bytes not found")); retourner; } // skip bytes (for http 1.1) return true;}JsonObject&WhiteWalnutApi::parseJson() { const size_t capacity =JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60; DynamicJsonBuffer jsonBuffer(capacity); JsonObject&root =jsonBuffer.parseObject(espSerial); if (!root.success()) Serial.println(F("Parsing failed!")); return root;}
WhiteWalnutApi.hArduino
#ifndef WHITEWALNUTAPI_H#define WHITEWALNUTAPI_H#include "Arduino.h"#include "ArduinoJson.h"#include "EcoActionBuffer.h"#include "Plant.h"class WhiteWalnutApi { public:static bool connectToWiFi(); static void updatePlant(Plant&plant); static void sendHumidity(Plant&plant, int humidity); static void sendHeartbeat(Plant&plant); static void receiveActionFromStack(EcoActionBuffer&actionBuffer); static void updateActionOnStack(EcoActionBuffer&actionBuffer); static void switchPin(int pin, bool value); private:static bool httpRequest(String site); static JsonObject&parseJson();};#endif

Schémas

Chart about the communication and interfaces All implemented intents you can ask Alexa, including the response.
(multilingual) If you are interested in the entrance step of your alexa json parsing.

Processus de fabrication

  1. Contrôleur DMX Web
  2. Arduino Spybot
  3. Système d'alarme Arduino :SERENA
  4. Boîte météo Arduino + ESP
  5. Système de ventilation du sous-sol/du vide sanitaire
  6. Système de présence basé sur Arduino et la feuille de calcul Google
  7. BLUE_P :Bouclier de programmation Arduino sans fil
  8. Système d'avertissement de détection de collision basé sur Arduino
  9. TFT Shield pour Arduino Nano - Démarrer