Меню Закрыть

Nodemcu отправка на thingspeak и озвучка Алисой

Примерно так будут выглядеть данные отправленные на сайт с Nodemcu
Примерно так будут выглядеть данные отправленные на сайт с Nodemcu

NodeMcu – платформа на основе ESP8266, аналог arduino с wi-fi модулем, что позволяет сразу из коробки взаимодействовать с устройствами в сети локальной или интернет.

Например с его помощью можно сделать умную лампочку, розетку, датчик показания которого можно отправить в интернет.

Предистория

Была у меня мечта не знаю зачем и почему, сделать мониторинг температуры в каждой комнате. Сначала когда то давным-давно я сделал это на ардуино и ds18b20, потом как то еще и на dht11. Позже делал в связке с arduino + orange pi pc. На оранж пай брал с серийного порта показания ds18b20 и писал вместе с датой в файл, морда была на php, можно было зайти и посмотреть температуру за прошедший период. По оранж пай отдельная тема, он у меня долгое время работал как приставка к телевизору витязь с kodi и плейлистами iptv.

Как это работает у меня сейчас

Теперь же в который раз я затеял все это на Nodemcu, сейчас у меня три платы с датчиками температуры ds18b20, dht11, dht22 и датчиками качества воздуха mq135. В каждой есть своя морда в локальной сети по статическому ip адресу, на главной плате которая в комнате страничка с iframe которая таким образом собирает все показания воедино и обновляется раз в 30 секунд обновляя все фреймы. Так же каждая из плат раз в 10 минут посылает данные на thingspeak.com. Из thingspeak.com их берет Алиса через навык кузя и озвучивает. С переходом на джино хостинг планирую еще отправлять на сайт.

Как я сделать страничку Nodemcu в локальной сети и статический ip адрес

Сначала я стал искать способ сделать страничку, что бы можно было выводить данные в локальную сеть и наткнулся на эту статью. Потом начал искать способ настроить статический ip адрес:

IPAddress ip(192,168,1,17); //статический IP IPAddress gateway(192,168,1,1); IPAddress subnet(255,255,255,0); void setup() { WiFi.config(ip, gateway, subnet); }
Code language: Arduino (arduino)

Отправка на thingspeak.com

Ещё хотелось данные куда отправлять что бы были видны показания из интернета. Нашел пример скетча отправляющего данные на thingspeak.com. Дальше расположив датчики в комнатах столкнулся с неудобством таскать их каждый раз к компу что бы поправить код, стал искать способ как можно прошить по wifi и нашел его.

В итоге

В итоге у меня получился такой код, на плате dht22 и mq135:

#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include "DHT.h" #include <MQ135.h> // подключение библиотеки #define analogPin A0 // аналоговый выход MQ135 подключен к пину A0 Arduino MQ135 gasSensor = MQ135(analogPin); // инициализация объекта датчика // Раскомментируйте одну из строк ниже в зависимости от того, какой датчик вы используете! //#define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 /* Введите свои SSID и пароль */ const char* ssid = "wifiname"; // SSID const char* password = "11111"; // пароль IPAddress ip(192,168,100,100); //статический IP IPAddress gateway(192,168,100,1); IPAddress subnet(255,255,255,0); ESP8266WebServer server(80); // датчик DHT uint8_t DHTPin = D2; //Пин датчика DHT22 (Совпадает с маркировкой nodemcu) // инициализация датчика DHT. DHT dht(DHTPin, DHTTYPE); float Temperature; //Переменная температуры float Humidity; //Переменная влажности unsigned long timing; // Переменная для хранения точки отсчета //Файл для загрузки должен иметь расширение *.bin #include <ESP8266HTTPUpdateServer.h> #define OTAUSER "admin" // Логин для входа в OTA #define OTAPASSWORD "admin" // Пароль для входа в ОТА #define OTAPATH "/firmware"// Путь, который будем дописывать после ip адреса в браузере. #define SERVERPORT 80 // Порт для входа, он стандартный 80 это порт http ESP8266HTTPUpdateServer httpUpdater; //----------------------------------------------------------------- void setup() { Serial.begin(115200); delay(100); pinMode(DHTPin, INPUT); //пин датчика DHT настраиваем на прием dht.begin(); Serial.println("Connecting to "); Serial.println(ssid); // подключаемся к локальной wi-fi сети WiFi.begin(ssid, password); WiFi.config(ip, gateway, subnet); //Строка отвечающая за статический ip 192.168.100.100, так же как и строки IPAddress выше // проверить, подключился ли wi-fi модуль к wi-fi сети while (WiFi.status() != WL_CONNECTED) // если не подключилось ждем секунду и отправляем точку { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected..!"); Serial.print("Got IP: "); Serial.println(WiFi.localIP()); //IP адрес Serial.print("macAddress: "); Serial.println(WiFi.macAddress()); //получаем MAC-адрес WeMos Serial.print("subnetMask: "); Serial.println(WiFi.subnetMask()); //маску подсети Serial.print("gatewayIP: "); Serial.println(WiFi.gatewayIP()); //IP- шлюза Serial.print("WiFi.SSID: "); Serial.println(WiFi.SSID());// имя сети, к которой подключен WeMos server.on("/", handle_OnConnect); server.onNotFound(handle_NotFound); server.begin(); Serial.println("HTTP server started"); httpUpdater.setup(&server, OTAPATH, OTAUSER, OTAPASSWORD); //OTA апдейтер, для прошивки по воздуху } int timer = 10 * 60 * 1000; //Таймер отправки на https://thingspeak.com/ void loop() { server.handleClient(); if (millis() - timing > timer){ // Если настоло время(таймер из переменной timer), то отправляем данные timing = millis(); Serial.println ("10 minut proshlo nachinaem otpravku"); float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); float ppm = gasSensor.getPPM(); // чтение данных концентрации CO2 float rzero = gasSensor.getRZero(); // чтение калибровочных данных sendTeperatureTS(temperature, humidity, ppm, rzero); //Функция отправки, код функции ниже } } void handle_OnConnect() //если набрал адрес платы { Temperature = dht.readTemperature(); // получить значение температуры Humidity = dht.readHumidity(); // получить значение влажности float ppm = gasSensor.getPPM(); // чтение данных концентрации CO2 float rzero = gasSensor.getRZero(); // чтение калибровочных данных server.send(200, "text/html", SendHTML(Temperature,Humidity, ppm, rzero, timing)); //SendHTML строка с html кодом страницы, чуть ниже код Serial.print("T:"); Serial.println(Temperature); Serial.print("H:"); Serial.println(Humidity); } void handle_NotFound() //если зашел на не существующий адрес { server.send(404, "text/plain", "Not found"); } String SendHTML(float Temperaturestat,float Humiditystat, float ppm, float rzero, int timing)//Строка с html кодом странички с нужными переменными с датчиков { char* vozduh = ""; //Условие взависимости от показаний ppm, выводит краткое пояснение о качестве воздуха. if(400>ppm){vozduh = "<p style='color: #329D27;'>Идеальный воздух для здоровья человека.</p>";} else{ if(600>ppm){vozduh = "<p style='color: #D8FA3F;'>Нормальное качество воздуха.</p>";} else { if(800>ppm){vozduh = "<p style='color: #A6A400;'>Не очень, появляются единичные жалобы на качество воздуха.</p>";} else{ if(1000>ppm){vozduh = "<p style='color: #A66600;'>Не очень, более частые жалобы на качество воздуха.</p>";} else{ if(2000>ppm){vozduh = "<p style='color: #A60C00;'>Плохой воздух. Общий дискомфорт, слабость, головная боль, проблемы с концентрацией внимания.</p>";} else { if(2000<ppm){vozduh = "<p style='color: #860049; font-size: 150%;'>Нельзя находится.</p>";} } } } } } int lastsend = (millis() - timing) / 1000 / 60; //Последняя отправка, переменная в которой вычисляется когда последний раз была отправка на thingspeak.com String ptr = "<!DOCTYPE html> <html>\n"; ptr +="<head><meta charset=utf-8 name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"; ptr +="<meta http-equiv=refresh content=30>"; //Автообновление страницы каждый 30 секунд ptr +="<title>"; //Тег заголовка страницы, удобно смотреть в заголовок вкладки и видеть основные данные ptr +=Temperaturestat; ptr +="°C|"; ptr +=Humiditystat; ptr +="%|"; ptr +=ppm; ptr +="ppm - NodeMcu</title>\n"; ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center; background: #485936;} #webpage{background: #fff; margin: 5px auto; padding: 5px; border-radius: 5px; max-width: 460px;} a{color: #93a368;}\n"; ptr +="body{margin-top: 50px;} h1 {color: #444444;}\n"; ptr +="p {font-size: 24px;color: #444444; margin:0px;}\n"; ptr +="h1{color: #444444; margin:0px;}\n"; ptr +="iframe{max-width: 265px; margin-left: 0px auto; border: 0px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<div id=\"webpage\">\n"; ptr +="<h1>Погода в комнате</h1>\n"; ptr +="<p>Температура: "; ptr +=Temperaturestat; ptr +="°C</p>"; ptr +="<p>Влажность: "; ptr +=Humiditystat; ptr +="%</p>"; ptr +="<p>Качество воздуха: "; ptr +=ppm; ptr +=" ppm<br>"; ptr +=vozduh; ptr +=" rzero: "; ptr +=rzero; ptr +="</p>"; ptr +="<h1 style='margin-bottom:0px;'>Погода в зале</h1>"; ptr +="<iframe style='height: 80px;' src='http://192.168.100.101'>Ваш браузер не поддерживает плавающие фреймы!</iframe>"; //Подгружаем фрейм с Nodemcu из зала ptr +="<h1>Погода на кухне</h1>\n"; ptr +="<iframe style='height: 200px;' src='http://192.168.100.102'>Ваш браузер не поддерживает плавающие фреймы!</iframe>";//Подгружаем фрейм с Nodemcu из кухни ptr +="<p style='font-size: 50%'>Последняя отправка на thingspeak.com: "; //Выводим сколько минут назад была последняя отправка ptr +=lastsend; ptr +=" минут назад.</p>"; ptr +="<p style='font-size: 50%'>ESP8266 NodeMCU Weather Report</p>"; ptr +="<p style='font-size: 50%'>Прошивка: <a href='http://192.168.100.100/firmware' target='_blank'>комната</a> | <a href='http://192.168.100.101/firmware' target='_blank'>зал</a> | <a href='http://192.168.100.102/firmware' target='_blank'>кухня</a></p>"; //ссылки на прошивку ptr +="</div>\n"; ptr +="</body>\n"; ptr +="</html>\n"; return ptr; } //функция отправки на thingspeak const char* server_send = "184.106.153.149"; String apiKey =""; //APIKEY ОБЯЗАТЕЛЬНО ЗАПОЛНИТЬ int sent=0; void sendTeperatureTS(float temp, float humidity, float ppm, float rzero) { WiFiClient client; Serial.println("(1)Connect to thingspeak."); int count = 2; int status_connect; while(!client.connect(server_send, 80)){ //если с первого раза не получилось соединиться с thingspeak.com ждем 10 секунд и выводим количество попыток Serial.print("("); Serial.print(count); Serial.println(")Connect to thingspeak."); delay(1000); } if (client.connect(server_send, 80)) { // use ip 184.106.153.149 or api.thingspeak.com //Serial.println("WiFi Client connected "); //отправка каждой переменной в нужный field String postStr = apiKey; postStr += "&field1="; postStr += String(temp); postStr += "&field2="; postStr += String(humidity); postStr += "&field4="; postStr += String(ppm); //postStr += "&field5="; // postStr += String(rzero); postStr += "\r\n\r\n"; client.print("POST /update HTTP/1.1\n"); client.print("Host: api.thingspeak.com\n"); client.print("Connection: close\n"); client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n"); client.print("Content-Type: application/x-www-form-urlencoded\n"); client.print("Content-Length: "); client.print(postStr.length()); client.print("\n\n"); client.print(postStr); delay(1000); Serial.println("Step sendTeperatureTS end"); }//end if else { Serial.println("thingspeak non conect"); } sent++; client.stop(); Serial.println("Step sendTeperatureTS exit"); }//end send
Code language: Arduino (arduino)

Озвучивание Алисой данных с thingspeak

По данному адресу будет фид канала такого вида:

{"channel":{"id":1293384,"name":"Home","description":"NodeMcu \u0026 DHT22 \u0026 MQ135 + NodeMcu \u0026 DS18B20 + Алиса озвучивает ","latitude":"0.0","longitude":"0.0","field1":"DHT22T","field2":"DHT22H","field3":"DS18B20","field4":"MQ135_PPM","field5":"DHT11T","field6":"DHT11H","field7":"MQ135_PPM","created_at":"2021-01-31T07:37:24Z","updated_at":"2021-03-08T18:56:29Z","last_entry_id":7159},"feeds":[{"created_at":"2021-03-08T19:01:19Z","entry_id":7159,"field1":null,"field2":null,"field3":null,"field4":null,"field5":"26.00","field6":"35.00","field7":"2514.08\r\n\r\n"}]}
Code language: JSON / JSON with Comments (json)

В данном моем случае что бы получить ответ по температуре и влажности field 1 и field 2 ответ кузи должен выглядеть так:

Температура {feeds.0.field1} градусов, Влажность {feeds.0.field2} процентов.

Отдельно стоит упомянуть что кузю нужно объединять с колонкой, а именно надиктовать ей код для того что бы объединить.

2 Comments

  1. никита

    привет! не могли бы вы мне помочь с чтением данных с dht11 на orange pi 3, я новичок в этих делах

  2. Vadim

    Добрый день! К сожалению я не знаю, знаю что это несколько сложнее чем с платами с поддержкой arduino ide

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Капча загружается...