Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Эко-система Herb Box

Компоненты и расходные материалы

Amazon Alexa Echo Dot
× 1
Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Arduino Proto Shield
× 1
Arduino 4 Relays Shield
× 1
Aqua Pump
× 2
Лампа для выращивания растений
× 1
Адаптер питания постоянного тока 220 В
× 1
Адаптер питания постоянного тока 12 В
× 1
USB-разъем питания + кабель
× 1
Воздушный шланг
× 1
Перемычки (общие)
× 1

Приложения и онлайн-сервисы

IDE Arduino
Amazon Alexa Alexa Skills Kit
Amazon Web Services AWS Lambda
веб-сервер php

Об этом проекте

Поскольку мои растения всегда страдают от слишком большого или меньшего количества воды, а мне нравится добавлять в посуду много трав, я решил создать индивидуальную систему орошения. Ящик для моих трав должен быть настраиваемым и работать автоматически или вручную. Поэтому существует интерфейс для веб-сайта, позволяющий настроить и отображать влажность на красивой диаграмме. Последним шагом была интеграция голосового управления, чтобы запросить у Amazon Alexa влажность, включить / выключить лампу для выращивания растений и запустить полив, если автоматизация отключена. Нажмите здесь, чтобы увидеть результат.

Я начал с технической части проекта и купил Arduino. После нескольких уроков я был твердо уверен в программном обеспечении и управлении Arduino. Я заказал контроллер Wi-Fi, датчики влажности, насосы, лампу для выращивания растений и дополнительное необходимое оборудование (защитный экран для отделения контуров лампы и насосов от Arduino, несколько проводов и буковую древесину для рамы). Код результата Arduino представлен в этом руководстве, а также некоторая информация о том, как использовать компоненты в ваших проектах. Код веб-сайта / API не предоставляется (если только спрос не очень высок;)).

Шаг первый:датчик влажности

Первой вехой было считывание влажности с помощью моего Arduino. Датчик влажности YL-69 легко подключить к Arduino. Вам необходимо подключить вывод VCC к выводу GPIO (в моем примере контакт 06), заземление к земле и A0 к аналоговому выводу (в моем примере вывод A1) Arduino.

Учебное пособие:датчик влажности почвы

  байт vccPin =6; byte dataPin =A1; void setup () {pinMode (vccPin, OUTPUT); digitalWrite (vccPin, LOW); Serial.begin (9600); while (! серийный);} int readHumidity () {digitalWrite (vccPin, HIGH); задержка (500); // вам нужно проверить, сколько времени вы предварительно включаете перед измерением int value =analogRead (dataPin); digitalWrite (vccPin, LOW); return 1023 - значение;} void loop () {Serial.print ("HumidityLevel (0-1023):"); Serial.println (readHumidity ()); задержка (10000);}  

Шаг второй:реле для насосов и лампы

Следующей целью была установка релейного щита (4 реле) для разделения цепей лампы, помпы и Ардуино. Arduino работает от 5 В, насосы используют 12 В, а лампа для выращивания растений - 230 В. Экран необходимо подключить к контактам 5V и заземления на Arduino. Каждому реле дополнительно нужен вывод GPIO по вашему выбору для включения и выключения. Наконец, вы можете использовать перемычку для подключения VCC JC к VCC на щите или использовать дополнительную батарею (что было бы лучше, но у меня пока нет батареи внутри моего проекта).

Важно понимать, что мой щит переключается "на" при "LOW" на контакте. Как только мой вывод будет определен как ВЫХОД, он автоматически станет активным. В коде вы всегда должны переключаться на INPUT и LOW, если вы хотите, чтобы реле было выключено. По умолчанию контакты Arduino - INPUT и LOW.

Учебное пособие:релейный экран

Информация:Почему реле OUTPUT + LOW =Active?

  байт pump1 =11; byte pump2 =10; void setup () {Serial.begin (9600); в то время как (! серийный); pinMode (насос1, ВЫХОД); // вариант низкий / высокий digitalWrite (pump2, LOW); // вариант ввода / вывода} void loop () {digitalWrite (pump1, HIGH); // pump1 деактивирован pinMode (pump2, INPUT); // задержка отключения насоса2 (1000); digitalWrite (pump1, LOW); // Pump1 активирован pinMode (pump2, OUTPUT); // задержка активации pump2 (1000);}  

Шаг третий:Wi-Fi с ESP-01

Подключение espressif ESP8266 ESP-01 к Arduino для Wi-Fi было самой сложной частью. Мне потребовалось несколько часов, чтобы включить Wi-Fi в моем скрипте.

ESP подключен к:VCC =3.3V, GND =GND, CH_PD =3.3V, TX =Pin 02, RX =Pin 03. Для продуктивного использования вы должны использовать как минимум преобразователь уровня от 5V до 3.3V для контакта. 02 и контакт 03 тоже. В моем случае все сработало нормально.

Подобно Arduino, ESP-01 - еще один микроконтроллер. Если вы хотите, чтобы оба контроллера обменивались данными, вы должны использовать последовательную связь. Arduino UNO по умолчанию использует контакты 01 и 02 для RX и TX. Но они также используются для отладки USB, поэтому рекомендуется включить SoftwareSerial.h и определить собственные контакты.

  #include  SoftwareSerial espSerial (3,2); // RX, TXvoid setup () {Serial.begin (9600); espSerial.begin (115200); // переключаемся на 9600 после AT + UART_DEF =9600,8,1,0,0 while (! Serial);} void loop () {if (espSerial.available ()) {Serial.write (espSerial.read ()); } если (Serial.available ()) {espSerial.write (Serial.read ()); }}  

Запустив приведенный выше сценарий, вы можете ввести AT-команды в монитор последовательного порта и увидеть результаты. Последовательная связь подвержена сбоям, поэтому я уменьшил скорость передачи данных, используемую ESP, с 115200 до 9600.

Учебник:ESP8266 + Arduino | Учебник:General ESP8266 (немецкий)

  • Полезный вспомогательный класс (но используется слишком много памяти):Библиотека:WiFiEsp
  • Инструмент проверки памяти:Библиотека:MemoryFree

Сценарий использует HTTP 1.0, потому что с HTTP 1.1 байты являются частью ответа. Важно позаботиться о разрывах строк для команды, отправляемой после AT + CIPSEND. Если они ошибочны, вы получите сообщение об ошибке отправки байта.

  #include  SoftwareSerial espSerial (3,2); // RX, TXconst char * ssid =""; const char * pass =""; void setup () {Serial.begin (9600); espSerial.begin (9600); в то время как (! серийный); пока (! connectToWiFi ()); // запросить веб-сайт и распечатать результат if (httpRequest ("my.server.com", "/site/subsite/index.php")) {while (espSerial.available ()) {Serial.write (espSerial.read () ); }}} void loop () {// запускать снова и снова if (espSerial.available ()) {Serial.write (espSerial.read ()); } если (Serial.available ()) {espSerial.write (Serial.read ()); }} bool connectToWiFi () {задержка (2000;) espSerial.setTimeout (3000); while (espSerial.available ()) Serial.write (espSerial.read ()); Serial.println (F ("[ESP] Подключение к WiFi")); espSerial.println (F ("AT + CIPSTATUS =2")); если (! espSerial.find ("ОК")) {espSerial.setTimeout (10000); Serial.println (F ("Модуль сброса [ESP]")); espSerial.println (F ("AT + RST")); if (! espSerial.find ("ready")) {Serial.println (F ("[ESP] Reset failed")); вернуть ложь; } Serial.println (F ("[ESP] Установить режим CWMode")); espSerial.println (F ("AT + CWMODE =1")); if (! espSerial.find ("OK")) {Serial.println (F ("Ошибка режима [ESP]")); вернуть ложь; } Serial.println (F ("[ESP] Подключиться к маршрутизатору")); espSerial.print (F ("AT + CWJAP =\" ")); espSerial.print (ssid); espSerial.print (F (" \ ", \" ")); espSerial.print (пройти); espSerial.println ("\" "); if (! espSerial.find ("OK")) {Serial.println (F ("Ошибка подключения [ESP] WiFi")); вернуть ложь; }} espSerial.setTimeout (3000); Serial.println (F ("[ESP] WiFi подключен")); return true;} bool httpRequest (строковый сервер, строковый сайт) {String cmd =""; cmd + ="ПОЛУЧИТЬ" + сайт + "HTTP / 1.0 \ r \ n"; cmd + ="Хост:" + сервер + "\ r \ n"; cmd + ="Подключение:закрыть"; интервал cmdLength =cmd.length () + 4; // Serial.println (cmd); espSerial.print (F ("AT + CIPSTART =\" TCP \ ", \" ")); espSerial.print (сервер); espSerial.println (F (" \ ", 80")); if (! espSerial.find ("OK")) {Serial.println (F ("[ESP] Ошибка соединения TCP")); вернуть ложь; } espSerial.print (F ("AT + CIPSEND =")); espSerial.println (cmdLength); if (! espSerial.find (findGT)) {Serial.println (F ("[ESP] Ошибка отправки состояния")); вернуть ложь; } espSerial.print (F ("ПОЛУЧИТЬ")); espSerial.print (сайт); espSerial.print (F ("HTTP / 1.0 \ r \ n")); espSerial.print (F ("Хост:")); espSerial.print (сервер); espSerial.print (F ("\ r \ n")); espSerial.print (F ("Соединение:закрыть \ r \ n")); espSerial.println (); if (! espSerial.find (":")) {Serial.println (F ("Байты не отправлены")); espSerial.print (F ("AT + CIPCLOSE")); вернуть ложь; } статус символа [32] ={0}; espSerial.readBytesUntil ('\ r', статус, sizeof (статус)); if (strcmp (status, "HTTP / 1.1 200 OK")! =0) {Serial.print (F ("[ESP] Неожиданный ответ:")); Serial.println (статус); вернуть ложь; } if (! espSerial.find ("\ r \ n \ r \ n")) {Serial.println (F ("[ESP] Неверный ответ")); вернуть ложь; } // Пропускаем заголовки HTTP // if (! EspSerial.find (\ r \ n)) {Serial.println (F ("[ESP] Байт не найдено")); возвращение; } // пропускаем байты (для http 1.1) return true; i}  

Шаг четвертый:деревянный ящик

В раме планировалось хранить всю электронику и три горшка с травами из супермаркета. Я замерил размеры всех компонентов и структурировал позиции. Четыре датчика влажности, два насоса, экран Arduino +, экран реле 4x, разъем USB и несколько проводов должны уместиться в коробке. Он был изготовлен из древесины бука, чтобы он был прочным и устойчивым к каплям воды без дополнительной глазури.

Круги выпиливались лобзиком на самодельном столе для лобзика. Крепления для растений приклеиваются внутрь кружков горячим клеем. Боковины ящика приклеены столярным клеем (Д3 для водонепроницаемости). Кроме электроники, я не использовал шурупы или гвозди рядом с креплением нижней панели.

Я поместил в коробку все цепи, провода и водяные трубки, вытащил датчики и трубки для дополнительного резервуара для воды. Перед тем, как закрыть коробку, я добавил блюдца, чтобы вода не утонула внутри коробки, чтобы защитить электронику.

Шаг пятый:API веб-сайта

API и веб-сайт основаны на jQuery, Bootstrap, X-editable (для встроенных форм ajax) и Chart.js (для диаграммы влажности), закодированных на php. На веб-сайте вы можете определить настройки для Arduino (например, контакты датчика, интервал проверки влажности, количество насосов на завод, контакты VCC насоса, контакт светового индикатора VCC) и найти текущую диаграмму влажности +.

Конфигурация предоставляется JSON для Arduino. После запуска и через частые интервалы ящик с травами проверяет наличие новых настроек. Для разбора JSON с помощью Arduino я использовал библиотеку ArduinoJson. Для интервала опроса я использовал StensTimer.

Библиотека:ArduinoJson | Библиотека:StensTimer

Шаг шестой:интеграция с Alexa

Веб-сайт предоставляет API для связи с Alexa. Он служит концентратором для получения запроса JSON от Alexa и переводит его в пользовательский JSON, используемый Arduino (например, лампа включена, орошение растения 1, ...). Arduino опрашивает новые действия и выполняет их.

Поскольку голосовые запросы - это больше, чем просто включение / выключение, я реализовал Alexa Skill, а не Alexa Smart Home. AWS Lampda перенаправляет запрос JSON в мой API, который анализирует намерения.

  var https =require ('https'); exports.handler =(событие, контекст, обратный вызов) => {var postData =JSON.stringify (событие); var options ={host:'', путь:'', порт:443, метод:'POST', заголовки:{'Content-Type':'application / json' , 'Content-Length':postData.length,}}; // настраиваем запрос 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));});}); // отправляем данные postRequest.write (postData); postRequest.end ();};  

Отрывок из намерений, которые я использовал в своих навыках:

  • ReadHumidityIntent Как мои растения
  • ReadHumidityIntent Как поживает мое {plantName}
  • IrrigatePlantIntent Орошение моих растений
  • IrrigatePlantIntent Орошение моего растения {plantName} в течение {durationSeconds} секунд
  • SwitchIntent Включить лампу {switchState}
  • ReadIrrigateIntent Какие растения нуждаются в воде
  • ReadLastIrrigationIntent Когда был последний полив моего растения {plantName}

И последнее, но не менее важное:я добавил поддержку локали для немецкого и английского языков.

Результат

В результате у меня есть деревянный ящик, в который можно положить горшки с травами из супермаркета, взять водяные трубки и датчики влажности в почве, а также трубки во внешний резервуар для воды. Благодаря интеграции с Alexa я могу сказать следующие предложения:

  • " Алекса, спроси ящик для трав, как мои растения "- Ответ:" Завод 1 в порядке, Завод 2 сухой, ... "
  • " Алекса, скажи ящику с травами поливать мой базилик в течение 5 секунд "- Ответ:" Орошение базилика в течение 5 секунд "
  • " Алекса, спроси ящик для трав, какие растения нуждаются в орошении "- Ответ:" Завод 1 сухой, Завод 3 сухой, ... "
  • " Алекса, спроси ящик для трав, когда было последнее орошение мой базилик "- Ответ:" Последний полив базилика был 36 часов назад "
  • " Алекса, скажи ящику с травами включить лампу "- Ответ:" Включена лампа для выращивания растений "

Спрашивать у Алексы влажность моего растения и потом поливать его (немецкий):

Просим Алексу включить лампу для выращивания растений:

GIF-файлы, показывающие результат без видео:

Планируемые функции

Следующие функции еще не реализованы, но запланированы на будущее:

  • Режим энергосбережения для исходного кода Arduino
  • Добавьте внешний Arduino Nanos с беспроводной связью (2,4 ГГц) для измерения влажности других растений в доме (коробка - это концентратор для WiFi) - с использованием только батарей.
  • Расширьте API для нескольких экземпляров коробки с травами, для друзей (и кого угодно, если вам интересно ?!)
  • Добавьте кнопку для полива и включения лампы на коробке без веб-сайта или Alexa.
  • Изображения Alexa (карточка в ответе на навык)

Обновление 23.03.2018

Я добавил два новых намерения. Один из них важен для запланированной функции внешних Adruino Nanos, которые просто регистрируют влажность.

  • Какие растения сухие
  • Когда был последний полив

Код

  • EcoActionBuffer.h
  • EcoActionBuffer.cpp
  • Plant.cpp
  • Plant.h
  • WhiteWalnut.ino
  • WhiteWalnutApi.cpp
  • WhiteWalnutApi.h
EcoActionBuffer.h Arduino
 #ifndef ECOACTIONBUFFER_H # define ECOACTIONBUFFER_H # include "Arduino.h" #include "StensTimer.h" struct EcoActionBuffer:public IStensTimerListener {long entryNo; int действие; int pin; большая продолжительность; void timerCallback (Таймер * таймер); void switchPin (int pin, bool value); void readStack (); void process (); void toSerial (); void reset ();}; # endif 
EcoActionBuffer.cpp Arduino
 #include "EcoActionBuffer.h" #include "StensTimer.h" #include "WhiteWalnutApi.h" #define ACTION_ECOACTION_READ 1 #define ACTION_ECOACTION_READ 1 # define ACTION_ECOACTION_HIGH 2 # define ACTION_ECOACTION_LOW 3void EcoActionBuffer ::readStack WhiteWalnutApi ::receiveActionFromStack (* this); если (номер записи! =0) {процесс (); // WhiteWalnutApi ::updateActionOnStack (* this); // отключено для повышения производительности}} void EcoActionBuffer ::process () {toSerial (); pinMode (вывод, ВЫХОД); digitalWrite (контакт, ВЫСОКИЙ); переключатель (действие) {case ACTION_ECOACTION_HIGH:switchPin (контакт, истина); ломать; case ACTION_ECOACTION_LOW:switchPin (контакт, ложь); ломать; } if (duration! =0) {StensTimer ::getInstance () -> setTimer (this, -pin, duration); }} void EcoActionBuffer ::timerCallback (Таймер * таймер) {переключатель (таймер-> getAction ()) {case ACTION_ECOACTION_READ:readStack (); ломать; } если (таймер-> getAction () <0) {switchPin (абс (таймер-> getAction ()), ложь); }} void EcoActionBuffer ::switchPin (int pin, bool value) {switch (value) {case true:digitalWrite (pin, LOW); ломать; case false:digitalWrite (pin, HIGH); ломать; } WhiteWalnutApi ::switchPin (контакт, значение);} void EcoActionBuffer ::reset () {entryNo =0; действие =0; pin =0; продолжительность =0;} void EcoActionBuffer ::toSerial () {Serial.print (entryNo); Serial.print (F ("- Действие:")); Serial.print (действие); Serial.print (F (", Pin:")); Serial.print (пин-код); Serial.print (F (", Продолжительность:")); Serial.print (продолжительность); Serial.println ();} 
Plant.cpp Arduino
 #include "Plant.h" #include "StensTimer.h" #include "WhiteWalnutApi.h" #define ACTION_PLANT_CHECKHUMIDITY 2 # define PIN_HUMIDITY_VCC 12void Plant ::checkHumidity () {if (влажностьDataPin! =0) {Serial.print (код); Serial.print (F («- Проверить влажность ...»)); digitalWrite (PIN_HUMIDITY_VCC, HIGH); задержка (200); // TODO int влажность =1023 - analogRead (влажностьDataPin); digitalWrite (PIN_HUMIDITY_VCC, LOW); Serial.println (влажность); WhiteWalnutApi ::sendHumidity (* this, влажность); if (влажностьCheckInterval ==0) влажностьCheckInterval =60000; StensTimer ::getInstance () -> setTimer (это, ACTION_PLANT_CHECKHUMIDITY, влажностьCheckInterval); } else StensTimer ::getInstance () -> setTimer (this, ACTION_PLANT_CHECKHUMIDITY, 60000);} void Plant ::updateApi () {WhiteWalnutApi ::updatePlant (* this); // WhiteWalnutApi ::sendHeartbeat (* this); // отключено для работы pinMode (PIN_HUMIDITY_VCC, OUTPUT); toSerial ();} void Plant ::timerCallback (Таймер * таймер) {переключатель (таймер-> getAction ()) {case ACTION_PLANT_CHECKHUMIDITY:checkHumidity (); ломать; }} void Plant ::toSerial () {Serial.print (код); Serial.print (F ("- DataPin:")); Serial.print (влажностьДатаПин); Serial.print (F (", Интервал:")); Serial.print (влажностьЧекинтервал); Serial.println ();} 
Plant.h Arduino
 #ifndef PLANT_H # define PLANT_H # include "Arduino.h" #include "StensTimer.h" struct Plant:public IStensTimerListener {const char * code; int влажностьDataPin; длительная влажностьCheckInterval; void checkHumidity (); void timerCallback (Таймер * таймер); void toSerial (); void updateApi ();}; # endif 
WhiteWalnut.ino Arduino
 #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_ADOACTION; в то время как (! серийный); stensTimer =StensTimer ::getInstance (); leftPlant.code ="ВЛЕВО"; centerPlant.code ="ЦЕНТР"; rightPlant.code ="ВПРАВО"; externalPlant.code ="ВНЕШНИЙ"; while (! WhiteWalnutApi ::connectToWiFi ()) задержка (2000); WhiteWalnutApi ::switchPin (0, ложь); 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 (Таймер * таймер) {переключатель (таймер-> getAction ()) {case ACTION_PLANT_UPDATE:updateApi (); ломать; }} 
WhiteWalnutApi.cpp Arduino
вам необходимо добавить настройки Wi-Fi и 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 ="готов"; 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] Подключение к WiFi")); espSerial.println (F ("AT + CIPSTATUS =2")); если (! espSerial.find (findOK)) {espSerial.setTimeout (10000); Serial.println (F ("Модуль сброса [ESP]")); espSerial.println (F ("AT + RST")); if (! espSerial.find (findRY)) {Serial.println (F ("[ESP] Reset failed")); вернуть ложь; } Serial.println (F ("[ESP] Установить режим CWMode")); espSerial.println (F ("AT + CWMODE =1")); if (! espSerial.find (findOK)) {Serial.println (F («Ошибка режима [ESP]»)); вернуть ложь; } Serial.println (F ("[ESP] Подключиться к маршрутизатору")); espSerial.print (F ("AT + CWJAP =\" ")); espSerial.print (ssid); espSerial.print (F (" \ ", \" ")); espSerial.print (пройти); espSerial.println ("\" "); if (! espSerial.find (findOK)) {Serial.println (F («[ESP] WiFi-соединение не удалось»)); вернуть ложь; }} espSerial.setTimeout (3000); Serial.println (F ("[ESP] WiFi подключен")); return true;} void WhiteWalnutApi ::updatePlant (Завод и завод) {String site =String (API_PLANT) + "? action =get &code =" + String (plant.code); while (! httpRequest (сайт)) connectToWiFi (); JsonObject &root =parseJson (); если (root.success ()) {plant.humidityDataPin =root ["dataPin"]. as  (); plant.humidityCheckInterval =atol (корень ["интервал"]. as  ()); }} void WhiteWalnutApi ::sendHumidity (Растение и растение, внутренняя влажность) {Строка site =Строка (API_PLANT) + «? действие =влажность &код =» + Строка (plant.code) + «&влажность =» + Строка (влажность); while (! httpRequest (сайт)) connectToWiFi (); // ЗАДАЧА:УДАЛИТЬ ВОЗВРАТ} 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 (); если (root.success ()) {actionBuffer.entryNo =atol (root ["entryNo"]. as  ()); actionBuffer.action =root ["actionEnum"]. as  (); actionBuffer.pin =root ["контакт"]. as  (); actionBuffer.duration =atol (корень ["значение"]. as  ()); }} void WhiteWalnutApi ::updateActionOnStack (EcoActionBuffer &actionBuffer) {Строка site =String (API_ACTION) + "? действие =обработано &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 ="+ Строка (значение); 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); / * Строка cmd =""; cmd + ="ПОЛУЧИТЬ" + сайт + "HTTP / 1.0 \ r \ n"; cmd + ="Хост:" + String (API_SERVER) + "\ r \ n"; cmd + ="Подключение:закрыть"; интервал cmdLength =cmd.length () + 4; Serial.println (cmd); * / int cmdLength =44 + site.length () + strlen (API_SERVER); // Serial.print (F ("[ПАМЯТЬ]")); // Serial.print (freeMemory ()); // Serial.print (F ("-")); // Serial.println (сайт); // -> 785 для внешнего espSerial.print (F ("AT + CIPSTART =\" TCP \ ", \" ")); espSerial.print (API_SERVER); espSerial.println (F (" \ ", 80") ); if (! espSerial.find (findOK)) {Serial.println (F ("[ESP] Ошибка соединения TCP")); вернуть ложь; } espSerial.print(F("AT+CIPSEND=")); espSerial.println(cmdLength); // espSerial.println(strlen(cmd)); if (!espSerial.find(findGT)) { Serial.println(F("[ESP] Send State Error")); вернуть ложь; } 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()); возвращение; if (!espSerial.find(findDP)) { Serial.println(F("Bytes not sent")); espSerial.print(F("AT+CIPCLOSE")); вернуть ложь; } 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); вернуть ложь; } // Check HTTP status if (!espSerial.find(findHD)) { Serial.println(F("[ESP] Invalid response")); вернуть ложь; } // Skip HTTP headers // if (!espSerial.find(findBT)) { Serial.println(F("[ESP] Bytes not found")); возвращение; } // 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

Схема

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.

Производственный процесс

  1. Веб-контроллер DMX
  2. Arduino Spybot
  3. Система сигнализации Arduino:SERENA
  4. Погодное окно Arduino + ESP
  5. Система вентиляции подвала / подвала
  6. Система посещаемости на основе Arduino и Google Spreadsheet
  7. BLUE_P:беспроводной экран программирования Arduino
  8. Система предупреждения об обнаружении столкновений на основе Arduino
  9. TFT Shield для Arduino Nano - запуск
  10. Arduino Shield NCS314 Tubes Clock IN-14