• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Мониторинг температуры через WEB

serenityLA

New member
Добрый день коллеги.

Друзья, я, к сожалению, не имею опыта программирования микроконтроллеров (ну на ардуино уно могу светодиодом по кнопке помигать). Но по долгу службы ( работаю в агрокомплексе) нужно собрать для руководства "систему" (громко сказано) мониторинга температуры и влажности помещения на 200 квадратных метров, которая бы выводила в реальном времени показатели на веб страницу на нашем сайте.
Немного погуглив, я примерно понял логику создания системы.

Нужно 5 датчиков ( по углам комнаты и в середине).
Планирую использоваться ESP8266 в связке с DHT22, так как на таком расстоянии использовать проводные контроллеры не очень удобно.

Соответственно эти 5 контроллеров должны отправлять информацию с датчиков в базу данных на веб сервере, а специально написанный скрипт (например на php) , генерит html страницу со схемой расположения датчиков и, соответственно, температурой каждого из них.

Это то, как я это вижу.

Я уже заставил один мой wemos D1 mini pro выводить температуру на веб страницу, но он у меня работает как веб сервер.

Вопрос, как это все реализовать практически ? )) я не очень понимаю, как написать программу, чтобы каждый esp отправлял инфу в БД и как на php написать скрипт, чтобы он правильно информацию считывал и выводил.

Заранее спасибо.
 

gerkimuyda

New member
serenityLA, Чтобы данные записывались синхронно в БД, можете функцию сбора показаний температур переложить на локальный сервер (php). Т.е. каждый датчик - это web-server, который по входящему запросу будет отдавать температуру. Все они цепляются на вай-фай апешку в роли клиента (STA). На сервере делаете по крону запуск пхп скрипта, который опрашивает все пять датчиков и записывает их значения (если датчик не отвечает - пишет NULL в БД (или "-100" если надо число)). Теперь в БД у вас есть все показания каждый период времени (каждую минуту, например, или каждые пять минут) и состояние датчика, если он отвалился.
пс: а если вам влажность не нужна, зачем тогда dht22 ? не проще ли ds18b20 ?

upd: обратный вариант - это на каждом датчике клиент, который POST запросом передает свои данные на центральный сервер. Минус этого метода - каждый датчик сам по себе по своему времени "пихает" значения в общую кучу, где все перемешано по временным меткам. Зато серверу не важно сколько датчиков и какие - т.к. датчики сами о себе заявляют.

Морда рисуется элементарно на пхп - один mysql запрос и вывод данных в html. Зато, в отличии от всяких блинков, система не зависит от наличия интернета и гарантированно работает с сохранением данных в архив (можно поднимать график температур за нужный период времени). o_O
Если выгрузку из БД делать по MIN группируя по дате - то получите график суточных ночных минимальных значений. Если по MAX - дневных максимальных. Если AVG - среднесуточную температуру.

При необходимости - можно сделать экспорт во всякие PDF, XLSX и рассылать ежедневный отчеты по всем емайлам руководству + уведомление SMS им :mad:
 
Последнее редактирование:

AndrF

Active member
На тему как бы делал я...

Для связи с внешним миром взял бы всего одну ESP-шку, для внутренней связи X+1 таких модулей, ну и X модулей Arduino Nano, где X-число датчиков.

ESP-шка, служащая для связи с внешним миром, стояла бы где-то в нормальном помещении и периодически получала сигналы с прочих модулей с автономным питанием раскиданным по теплицам (расстояние, как пишут, до километра). С Web-сайтом даже не стал бы заморачиваться. Начальству ведь что надо - чтобы было удобно в любое время посмотреть что твориться в хозяйстве. А удобнее всего это делать со смартфона, который всегда под рукой. Так что Blynk тут вполне впишется. В итоге все оказывается достаточно просто в реализации и можно собрать без изготовления печатных плат (хотя последнее в наше время совсем не проблема).

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

IMHO, конечно.
 

serenityLA

New member
serenityLA, Чтобы данные записывались синхронно в БД, можете функцию сбора показаний температур переложить на локальный сервер (php). Т.е. каждый датчик - это web-server, который по входящему запросу будет отдавать температуру. Все они цепляются на вай-фай апешку в роли клиента (STA). На сервере делаете по крону запуск пхп скрипта, который опрашивает все пять датчиков и записывает их значения (если датчик не отвечает - пишет NULL в БД (или "-100" если надо число)). Теперь в БД у вас есть все показания каждый период времени (каждую минуту, например, или каждые пять минут) и состояние датчика, если он отвалился.
пс: а если вам влажность не нужна, зачем тогда dht22 ? не проще ли ds18b20 ?

upd: обратный вариант - это на каждом датчике клиент, который POST запросом передает свои данные на центральный сервер. Минус этого метода - каждый датчик сам по себе по своему времени "пихает" значения в общую кучу, где все перемешано по временным меткам. Зато серверу не важно сколько датчиков и какие - т.к. датчики сами о себе заявляют.

Морда рисуется элементарно на пхп - один mysql запрос и вывод данных в html. Зато, в отличии от всяких блинков, система не зависит от наличия интернета и гарантированно работает с сохранением данных в архив (можно поднимать график температур за нужный период времени). o_O
Если выгрузку из БД делать по MIN группируя по дате - то получите график суточных ночных минимальных значений. Если по MAX - дневных максимальных. Если AVG - среднесуточную температуру.

При необходимости - можно сделать экспорт во всякие PDF, XLSX и рассылать ежедневный отчеты по всем емайлам руководству + уведомление SMS им :mad:
Спасибо за ответ.

Очень понравился ваш вариант, так как я примерно так себе это и представлял. Вопрос исключительно в практике, так как мне недостаточно знаний. Но я готов разбираться до последнего, ибо тема очень интересная для меня ).

Потому буду последовательно задавать вопросы. ( если бы могли с Вами связаться в скайпе например, было бы отлично).

Сначала попробую у себя дома создать данную систему.
Что у меня в наличии:

2 -wemos D1 mini Pro
1 - Wemos D1 с ESP 12s на борту
1 - arduino uno
3 - датчика DHT 22
1 - DHT 11

Предположим, что реализуем систему по вашему первому варианту.

Локальный сервер установил MAMP.

Каждый из D1 у меня веб сервер в режиме STA. WI-FI "апешка" это мой роутер ?
cron php script надо изучить я так понимаю, чтобы понять как правильно написать запросы к каждой плате.

Влажность нужна, ds как вариант уже исключили.

Морда - интерфейс страницы, я так понимаю ), нужно выяснить как писать правильно запрос )
 
Последнее редактирование:

gerkimuyda

New member
Каждый из D1 у меня веб сервер в режиме STA. WI-FI "апешка" это мой роутер ?
cron php script надо изучить я так понимаю, чтобы понять как правильно написать запросы к каждой плате.

Влажность нужна, ds как вариант уже исключили.

Морда - интерфейс страницы, я так понимаю ), нужно выяснить как писать правильно запрос )
"апешка" - это ваш вай-фай роутер.
Да, начинайте по-этапно. С начала сделайте и отладьте свои модули с датчиками. Это вам даст возможность уже отслеживать температуру, пока занимаетесь остальным.
У них в ответ можете отдавать или кратко "имя, температуру, влажность" , чтобы зайдя с мобилки или компа можно было посмотреть, или (если надо) можете сразу json отдавать.

Далее: создаете php-скрипт, который обращается к одному модулю, получает его значение и записывает в БД (с обработкой варианта не ответа модулем, если он выключен).
потом: cron - это планировщик в юниксах, если винда - тоже можно создать планировщик в
Пуск -> Панель управления -> Администрирование -> Планировщик заданий -> Создать задачу
где опишите запуск php.exe с передачей ему пути к вашему скрипту в параметрах командной строки.

Когда отработаете на одном модуле - делаете опрос всех 5 модулей. А из планировщика у вас автоматом постоянно запускается этот опрос.

Теперь можно перейти к рисованию web-странички, на которой будете выводить значения.

Делайте поэтапно и задавайте вопросы. По мере продвижения буду подсказывать (или другие участники форума). Про wemos не подскажу, у меня NodeMCU. А вот про всякие php и mysql - как два байта переслать o_O
 

serenityLA

New member
"апешка" - это ваш вай-фай роутер.
Да, начинайте по-этапно. С начала сделайте и отладьте свои модули с датчиками. Это вам даст возможность уже отслеживать температуру, пока занимаетесь остальным.
У них в ответ можете отдавать или кратко "имя, температуру, влажность" , чтобы зайдя с мобилки или компа можно было посмотреть, или (если надо) можете сразу json отдавать.

Далее: создаете php-скрипт, который обращается к одному модулю, получает его значение и записывает в БД (с обработкой варианта не ответа модулем, если он выключен).
потом: cron - это планировщик в юниксах, если винда - тоже можно создать планировщик в
Пуск -> Панель управления -> Администрирование -> Планировщик заданий -> Создать задачу
где опишите запуск php.exe с передачей ему пути к вашему скрипту в параметрах командной строки.

Когда отработаете на одном модуле - делаете опрос всех 5 модулей. А из планировщика у вас автоматом постоянно запускается этот опрос.

Теперь можно перейти к рисованию web-странички, на которой будете выводить значения.

Делайте поэтапно и задавайте вопросы. По мере продвижения буду подсказывать (или другие участники форума). Про wemos не подскажу, у меня NodeMCU. А вот про всякие php и mysql - как два байта переслать o_O

Сейчас подключил свой первый ESP в качестве STA и настроил вывод датчика температуры на порт. Не могу понять как сделать вывод на веб страницу.

Код:
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <DHT.h>
#define DHTPIN D4
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

const char* ssid = "Мой WIFI";
const char* password = "мой пароль";

void setup() {
    Serial.begin(9600);
    WiFi.mode (WIFI_STA);
    WiFi.begin (ssid, password);
         while(WiFi.waitForConnectResult() !=WL_CONNECTED)
              {delay(5000); ESP.restart();}
    Serial.println("DHTxx test!");
    dht.begin();        
  //ArduinoOTA.setPort (8266);
  ArduinoOTA.setHostname("AHTOH ESP1");
  //ArduinoOTA.setPassword((const char *)"123");
  ArduinoOTA.onStart      ([] (){/*code*/;});
  ArduinoOTA.onEnd        ([] (){/*code*/;});
  ArduinoOTA.onProgress   ([] (uint16_t i, uint16_t){/*code*/;});
  ArduinoOTA.onError    ([] (ota_error_t error   ){/*code*/;});
  ArduinoOTA.begin      ();
}

void loop() {
  ArduinoOTA.handle();

  delay(5000);

  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Impossible de lire la sonde DHT!");
    return;
  }
 
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C ");
  Serial.println();

}
 

gerkimuyda

New member
Пример простейшего web:

Код:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
void handleRoot() { server.send(200, "text/html", "<!DOCTYPE HTML>\r\n<html>Hello!</html>"); }
void setup() {
  WiFi.begin("ssid", "password");
  server.on("/", handleRoot);
  server.begin();
}
void loop() {  server.handleClient(); }
В вашем случае: [inline]"Name: Sensor1\r\nTemperature: "+String(t)+"Humidity: "+String(h);[/inline]
 

serenityLA

New member
Пример простейшего web:

Код:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
void handleRoot() { server.send(200, "text/html", "<!DOCTYPE HTML>\r\n<html>Hello!</html>"); }
void setup() {
  WiFi.begin("ssid", "password");
  server.on("/", handleRoot);
  server.begin();
}
void loop() {  server.handleClient(); }
В вашем случае: [inline]"Name: Sensor1\r\nTemperature: "+String(t)+"Humidity: "+String(h);[/inline]

Что-то не выводит он hello при заходе на ip контроллера.
(хотя возможно это потому, что я использую ipad как точку доступа )), через него даже на локалхост не получается зайти вводя IP моего PC).

Тогда пока нету доступа к роутеру, попробую разобраться с php.
В интернете нашел такой скрипт :
PHP:
<?php

    // Prepare variables for database connection
  
    $dbusername = "arduino";  // enter database username, I used "arduino" in step 2.2
    $dbpassword = "arduinotest";  // enter database password, I used "arduinotest" in step 2.2
    $server = "localhost"; // IMPORTANT: if you are using XAMPP enter "localhost", but if you have an online website enter its address, ie."www.yourwebsite.com"

    // Connect to your database

    $dbconnect = mysql_pconnect($server, $dbusername, $dbpassword);
    $dbselect = mysql_select_db("test",$dbconnect);

    // Prepare the SQL statement

    $sql = "INSERT INTO test.sensor (value) VALUES ('".$_GET["value"]."')";   

    // Execute SQL statement

    mysql_query($sql);

?>
Но как я понял это только коннект к БД но не вывод ?
 

kab

New member
Что-то не выводит он hello при заходе на ip контроллера.
(хотя возможно это потому, что я использую ipad как точку доступа )), через него даже на локалхост не получается зайти вводя IP моего PC).

Тогда пока нету доступа к роутеру, попробую разобраться с php.
В интернете нашел такой скрипт :
PHP:
<?php

    // Prepare variables for database connection
 
    $dbusername = "arduino";  // enter database username, I used "arduino" in step 2.2
    $dbpassword = "arduinotest";  // enter database password, I used "arduinotest" in step 2.2
    $server = "localhost"; // IMPORTANT: if you are using XAMPP enter "localhost", but if you have an online website enter its address, ie."www.yourwebsite.com"

    // Connect to your database

    $dbconnect = mysql_pconnect($server, $dbusername, $dbpassword);
    $dbselect = mysql_select_db("test",$dbconnect);

    // Prepare the SQL statement

    $sql = "INSERT INTO test.sensor (value) VALUES ('".$_GET["value"]."')"; 

    // Execute SQL statement

    mysql_query($sql);

?>
Но как я понял это только коннект к БД но не вывод ?
Пока @gerkimuyda не в сети, попытаюсь пообщаться :):):)

С php я не очень, но насчет SQL вижу:

- "INSERT INTO ..." - это значит вставить строчку в таблицу БД, т.е. это не только коннект к БД, но и её наполнение.

Чтобы из таблицы БД что-то вывести, надо сначала данные занести в переменную. Выражение SQL будет похожее, только начинаться с "SELECT INTO ...". Ну там ещё, конечно, есть тонкости...
 

kab

New member
Тогда пока нету доступа к роутеру
Кстати, если с роутером проблемы - несложно запустить ESP в режиме точки доступа. Например, с смартфона сразу сможете подключиться к нему. Примеры есть в Arduino IDE. Ключевая строчка

 

gerkimuyda

New member
Начнем с азов. Чтобы подключаться к mysql надо сначала создать нужную таблицу. Что у вас там будет?
id, sensor, temperature, humidity, datetime

Создаем пользователя и БД для него. В этой БД создаем таблицу для наших данных `serenity` - таким sql запросом (в phpmyadmin или navicat или в подобных прогах):

Код:
--
-- Структура таблиці `serenity`
--

CREATE TABLE `serenity` (
  `id` int(10) UNSIGNED NOT NULL,
  `sensor` varchar(20) NOT NULL,
  `temperature` decimal(5,2) DEFAULT NULL,
  `humidity` decimal(5,2) DEFAULT NULL,
  `datetime` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Індекси таблиці `serenity`
--
ALTER TABLE `serenity`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT для таблиці `serenity`
--
ALTER TABLE `serenity`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;COMMIT;
Тут у нас [inline]id[/inline]- индификатор записи, [inline]sensor[/inline] - имя сенсора (или его адресс), [inline]temperature[/inline] - температура, [inline]humidity[/inline] - влажность, [inline]datetime[/inline] - время записи данных.
Температуру и Влажность мы сделали с записью сотых (два знака после запятой) и добавили возможность писать [inline]NULL[/inline], если опрашиваемый датчик не отвечает.

Теперь можно из php подключится и записать данные:
PHP:
<?php
  $db_server    =    "localhost";
  $db_username    =    "arduino";
  $db_password    =    "arduinotest";
  $db_database    =    "arduino";
  $db = mysqli_connect($db_server, $db_username, $db_password, $db_database);
  if(!$db) { print "MySQL Error: ".mysqli_connect_error(); exit; }

  $sensor_name     =     '#1 (SouthWest)';
  $sensor_temperature    =     '21.15';
  $sensor_humidity    =    '66.55';

  $sql = "INSERT INTO `serenity` (`sensor`, `temperature`, `humidity`, `datetime`) ".
     "VALUES ('".mysqli_real_escape_string($db, $sensor_name)."', ".
     "'".mysqli_real_escape_string($db, $sensor_temperature)."', ".
     "'".mysqli_real_escape_string($db, $sensor_humidity)."', NOW()); ";
  mysqli_query($db,$sql);
  $error = mysqli_error($db);
  if($error) { print "MySQL Error: ".$error; exit; }
print "Done.";
В поле [inline]datetime[/inline] мы подставляем текущее дату и время сервера функцией [inline]NOW()[/inline]

Рекомендации:
- используйте mysqli, т.к. mysql в php7 устаревший и осужден
- в конце кода не закрывайте [inline]?>[/inline], дабы не выводить лишние и не нужные символы (пробел, табуляция, перевод строки), которые html не поломают, а вот какой-то другой ответ могут повредить
- всегда используйте mysqli_real_escape_string, чтобы исключить хак вашего кода через SQL-инъекции
- всегда делайте проверки ошибок (в данном случае: подключение mysqli и выполнение запроса)

---------------------------

Чтобы из таблицы БД что-то вывести, надо сначала данные занести в переменную. Выражение SQL будет похожее, только начинаться с "SELECT INTO ...". Ну там ещё, конечно, есть тонкости...
В данном случае ваш код не подходит, т.к. вы написали запрос на заполнение таблицы данными, получаемыми из другой таблицы. А нам из других таблиц ничего брать не надо (в данном случае).

Что-то не выводит он hello при заходе на ip контроллера.
Разбирайтесь. Если смарт даже на комп не может достучаться, то тут явная проблема у вас с настройками.
Но как я понял это только коннект к БД но не вывод ?
В вашем случае это будут разные скрипты: один для сбора данных с датчиков и запись в БД, и второй - вывод данных из БД и формирование html странички для отображения.
 
Последнее редактирование:

serenityLA

New member
Начнем с азов. Чтобы подключаться к mysql надо сначала создать нужную таблицу. Что у вас там будет?
id, sensor, temperature, humidity, datetime

Создаем пользователя и БД для него. В этой БД создаем таблицу для наших данных `serenity` - таким sql запросом (в phpmyadmin или navicat или в подобных прогах):

Код:
--
-- Структура таблиці `serenity`
--

CREATE TABLE `serenity` (
  `id` int(10) UNSIGNED NOT NULL,
  `sensor` varchar(20) NOT NULL,
  `temperature` decimal(5,2) DEFAULT NULL,
  `humidity` decimal(5,2) DEFAULT NULL,
  `datetime` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Індекси таблиці `serenity`
--
ALTER TABLE `serenity`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT для таблиці `serenity`
--
ALTER TABLE `serenity`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;COMMIT;
Тут у нас [inline]id[/inline]- индификатор записи, [inline]sensor[/inline] - имя сенсора (или его адресс), [inline]temperature[/inline] - температура, [inline]humidity[/inline] - влажность, [inline]datetime[/inline] - время записи данных.
Температуру и Влажность мы сделали с записью сотых (два знака после запятой) и добавили возможность писать [inline]NULL[/inline], если опрашиваемый датчик не отвечает.

Теперь можно из php подключится и записать данные:
PHP:
<?php
  $db_server    =    "localhost";
  $db_username    =    "arduino";
  $db_password    =    "arduinotest";
  $db_database    =    "arduino";
  $db = mysqli_connect($db_server, $db_username, $db_password, $db_database);
  if(!$db) { print "MySQL Error: ".mysqli_connect_error(); exit; }

  $sensor_name     =     '#1 (SouthWest)';
  $sensor_temperature    =     '21.15';
  $sensor_humidity    =    '66.55';

  $sql = "INSERT INTO `serenity` (`sensor`, `temperature`, `humidity`, `datetime`) ".
     "VALUES ('".mysqli_real_escape_string($db, $sensor_name)."', ".
     "'".mysqli_real_escape_string($db, $sensor_temperature)."', ".
     "'".mysqli_real_escape_string($db, $sensor_humidity)."', NOW()); ";
  mysqli_query($db,$sql);
  $error = mysqli_error($db);
  if($error) { print "MySQL Error: ".$error; exit; }
print "Done.";
В поле [inline]datetime[/inline] мы подставляем текущее дату и время сервера функцией [inline]NOW()[/inline]

Рекомендации:
- используйте mysqli, т.к. mysql в php7 устаревший и осужден
- в конце кода не закрывайте [inline]?>[/inline], дабы не выводить лишние и не нужные символы (пробел, табуляция, перевод строки), которые html не поломают, а вот какой-то другой ответ могут повредить
- всегда используйте mysqli_real_escape_string, чтобы исключить хак вашего кода через SQL-инъекции
- всегда делайте проверки ошибок (в данном случае: подключение mysqli и выполнение запроса)

---------------------------


В данном случае ваш код не подходит, т.к. вы написали запрос на заполнение таблицы данными, получаемыми из другой таблицы. А нам из других таблиц ничего брать не надо (в данном случае).


Разбирайтесь. Если смарт даже на комп не может достучаться, то тут явная проблема у вас с настройками.

В вашем случае это будут разные скрипты: один для сбора данных с датчиков и запись в БД, и второй - вывод данных из БД и формирование html странички для отображения.

Я создал скрипт php

PHP:
<?php
define ('DBHOST', '192.168.14.102');
define ('DBNAME', 'esp'); // Имя базы данных
define ('DBUSER', 'arduino'); // Пользователь базы
define ('DBPASS', 'arduinotest'); // Пароль БД
/* Подключение к БД */
mysql_connect(DBHOST, DBUSER, DBPASS) or die('Соединение отсутсвует!');
mysql_select_db(DBNAME) or die ('Соединение с БД отсутсвует!');
mysql_query('SET NAMES utf8');

$id = ($_GET['id']);
$temp = ($_GET['t']);
$hum = ($_GET['h']);
if ($id == '1') {
    $total = mysql_result(mysql_query("SELECT count(*) FROM `esp1`"),0);
    mysql_query("INSERT INTO `esp1` (temp,hum) values ('".$temp."','".$hum."') ");
}
/*if ($id == '2') {
    $total = mysql_result(mysql_query("SELECT count(*) FROM `esp2`"),0);
    mysql_query("INSERT INTO `esp2` (temp,hum) values ('".$temp."','".$hum."') ");
}
if ($id == '3') {
    $total = mysql_result(mysql_query("SELECT count(*) FROM `esp3`"),0);
    mysql_query("INSERT INTO `esp3` (temp,hum) values ('".$temp."','".$hum."') "); */
}
echo 'Ок';
?>
В ESP загрузил такой код

Код:
#include "DHT.h"
#define DHTPIN D4
#define DHTTYPE DHT22   
#include <ESP8266WiFi.h>
const char* ssid= "xxxx";
const char* password = "xxxx";
const int httpPort = 8080;
const char* host = "192.168.14.102";
#define DHTPIN D4   
#define DHTTYPE DHT22   
DHT dht(DHTPIN, DHTTYPE, D4);
void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password); 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
Serial.println(WiFi.localIP());
}
void loop() { 
    delay(2000);
   float h = dht.readHumidity();
   float t = dht.readTemperature();
   float f = dht.readTemperature(true);
    if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  } 
   WiFiClient client;
   if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
String url = "/esp.php?";
    url += "id=1";
    url += "&t=";
    url += t;
    url += "&h=";
    url += h;
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n"); 
}
В БД вписал

Код:
CREATE TABLE IF NOT EXISTS `esp1` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `temp` float NOT NULL,
  `hum` float NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_2` (`id`),
  KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;



CREATE TABLE IF NOT EXISTS `esp2` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `temp` float NOT NULL,
  `hum` float NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_2` (`id`),
  KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;



CREATE TABLE IF NOT EXISTS `esp3` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `temp` float NOT NULL,
  `hum` float NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_2` (`id`),
  KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Но при мониторинге порта выводит connection failed. не понимаю где ошибка, все данные подключения указаны верно
 

gerkimuyda

New member
Применяемые вами методы совсем другие, чем те, которые я вам давал.
Я вам приводил действующий рабочий вариант http-сервера, а с тем, который вы пытаетесь использовать, уже возникали разные проблемы.

Правильный скрипт записи в БД я вам тоже написал уже готовый. Тот который вы предлагаете:
- не будет работать на php7 (устаревшие функции, которые больше не поддерживаются),
- подвержен взлому через sql-инъекции,
- не содержит адрес/имя сенсора (не подходит для нескольких сенсоров в одной таблице),
- не содержит время записи.

Создавать отдельные таблицы для каждого сенсора - моветон, это как файлы раскладывать каждый в отдельную поддиректорию. К тому-же, лишает возможности оперировать одним запросом сразу со всеми датчиками.

Применяемый вами подход пригоден для передачи скрипту GET запроса с данными, а вам надо наоборот - скриптом забирать данные с модулей (к этому в моем примере мы еще не подошли).

Если у вас проблемы с dhcp и ip адресами, можете в модули прописать каждому фиксированный ip адрес, без запросов к dhcp.

пс: я понимаю ваше желание более тесно пообщаться и быстрее реализовать свой код, но сейчас идут риздвяни праздники, рождество и новый год - выходные, дома праздничная обстановка и прыгают дети :) поэтому на форуме я набегами o_O
ппс: php7+mysql(mariadb) - это моя специализация, так что в этом вопросе можете доверять моим словам. Рекомендую более подробнее изучать и разбирать предлагаемые мною способы, чем искать другие дилетантские, содержащие ошибки.
 
Последнее редактирование:
  • Like
Реакции: kab

serenityLA

New member
Применяемые вами методы совсем другие, чем те, которые я вам давал.
Я вам приводил действующий рабочий вариант http-сервера, а с тем, который вы пытаетесь использовать, уже возникали разные проблемы.

Правильный скрипт записи в БД я вам тоже написал уже готовый. Тот который вы предлагаете:
- не будет работать на php7 (устаревшие функции, которые больше не поддерживаются),
- подвержен взлому через sql-инъекции,
- не содержит адрес/имя сенсора (не подходит для нескольких сенсоров в одной таблице),
- не содержит время записи.

Создавать отдельные таблицы для каждого сенсора - моветон, это как файлы раскладывать каждый в отдельную поддиректорию. К тому-же, лишает возможности оперировать одним запросом сразу со всеми датчиками.

Применяемый вами подход пригоден для передачи скрипту GET запроса с данными, а вам надо наоборот - скриптом забирать данные с модулей (к этому в моем примере мы еще не подошли).

Если у вас проблемы с dhcp и ip адресами, можете в модули прописать каждому фиксированный ip адрес, без запросов к dhcp.

пс: я понимаю ваше желание более тесно пообщаться и быстрее реализовать свой код, но сейчас идут риздвяни праздники, рождество и новый год - выходные, дома праздничная обстановка и прыгают дети :) поэтому на форуме я набегами o_O
ппс: php7+mysql(mariadb) - это моя специализация, так что в этом вопросе можете доверять моим словам. Рекомендую более подробнее изучать и разбирать предлагаемые мною способы, чем искать другие дилетантские, содержащие ошибки.
Я Вас понимаю и очень благодарен за то, что находите время отвечать на мои дилетантские вопросы. Я вообще удивлен, что в нынешнее время возможно нормальное общение на форумах в рунете, вы же знаете как это бывает, новичок спрашивает - ему отвечают "не лезь в этой дело" - это если мягко выражаться.

Я прошу прощения, что не разобрался с вашим прошлым постом, так как наткнулся на "готовое" решение и подумал, что можно его применить.
Сделал все как Вы описали. ESP выводит "Hello" при заходе на его IP. В бд вставил код. PHP скрипт создал. Вхожу на адрес скрипта - добавляется строчка в БД - значит все работает. Теперь, я так понимаю, нужно доработать скрипт, чтобы он обращался к каждому веб серверу (каждому отдельному esp) и написать саму программу для ESP чтобы она в определенном виде выводила данные, дабы скрипт мог их понять ?

Так у меня сейчас выглядит код в ESP:

*чисто для общего развития
Я подключил два датчика к D4 и D2, но не могу понять как правильно написать в server.send , чтобы он показывал данные со второго датчика на новой строке, тег <br> не распознается ) :
Код:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#define DHTPIN D4
#define DHTPIN2 D2
#define DHTTYPE DHT22
ESP8266WebServer server(80);
DHT dht(DHTPIN, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);
void handleRoot() {
 
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float h2 = dht2.readHumidity();
  float t2 = dht2.readTemperature();
 
  if (isnan(h) || isnan(t)) {
    Serial.println("DHT22 недоступен.");
    return;
  }
  server.send(200, "text/html", "Name: Sensor 1\r\n Temperature: "+String(t)+"Humidity: "+String(h) +". " + "Name: Sensor 2\r\n Temperature: "+String(t2)+"Humidity: "+String(h2));
  }
void setup() {
  WiFi.begin("xxxxxx", "xxxxxx");
  server.on("/", handleRoot);
  server.begin();
  Serial.println("DHTxx test!");
    dht.begin();
 
}
void loop() {
  server.handleClient();
}
Собственно - он выводит по IP.

Name: Sensor 1 Temperature: 24.60Humidity: 36.60. Name: Sensor 2 Temperature: 24.80Humidity: 33.80

И еще такой вопрос.
Я использую связку wemos d1 mini pro +dht22 на плате trema. Если верить тех.спецификации датчика, для нормального (максимально точного) функционирования ему требуется напряжение от 3.3В. У меня есть батареечный блок, для двух батареек на 3.7В. Правильно ли понимаю, что общее напряжение на плату будет идти 7.4 В, но максимальное, которое плата будет получать - 5В . Собственно, количество датчиков ограничивается количеством in/out на плате, а напряжение 5В будет постоянным (пока не сядут батарейки) и его хватит на все датчики ? Да простит меня мой преподаватель по физике в школьные годы за прогулы.....
 
Последнее редактирование:
  • Like
Реакции: kab

gerkimuyda

New member
Теперь, я так понимаю, нужно доработать скрипт, чтобы он обращался к каждому веб серверу (каждому отдельному esp) и написать саму программу для ESP чтобы она в определенном виде выводила данные, дабы скрипт мог их понять ?
Правильно. Начнем с одного датчика, потом остальные обработаем через цикл.
PHP:
  $sensor_address    =    'http://192.168.100.1/';
  $ctx = stream_context_create( array('http' => array('timeout' => 3) ) );
  $res = file_get_contents($sensor_address, 0, $ctx);
не могу понять как правильно написать в server.send , чтобы он показывал данные со второго датчика на новой строке, тег <br> не распознается ) :
В приведенном вами коде вы выводите не html, а обычный текст, хотя в заголовке указываете, что у вас не [inline]text/plain[/inline], а [inline]text/html[/inline]
Вам надо определиться и прийти к одному формату. Для html тег перевода строки [inline]<br/>[/inline], для текста новая строка [inline]\r\n[/inline].

Только продумайте, в каком виде у вас будет вывод данных, т.к. из этого формата вам потом на php вытягивать данные.
Если html, попробуйте воспользоваться тегами, для выделения значений, например:
HTML:
<p>Temperature: <span id='temp'>17.08</span></p>
теперь вы сможете искать [inline]<span id='temp'>[/inline] и вырезать до [inline]</span>[/inline] значение температуры.

И еще такой вопрос.
Я использую связку wemos d1 mini pro +dht22 на плате trema.
Это вопрос к другим участникам, т.к. у меня нет wemos и я не могу подсказать по ним ничего.
 
Последнее редактирование:

serenityLA

New member
В приведенном вами коде вы выводите не html, а обычный текст, хотя в заголовке указываете, что у вас не [inline]text/plain[/inline], а [inline]text/html[/inline]
Вам надо определиться и прийти к одному формату. Для html тег перевода строки [inline]<br/>[/inline], для текста новая строка [inline]\r\n[/inline].
Я не понимаю, как должна выглядеть функция ?

В таком виде не компилирует:

Код:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#define DHTPIN D4
#define DHTPIN2 D2
#define DHTTYPE DHT22
ESP8266WebServer server(80);


DHT dht(DHTPIN, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);

void handleRoot() {
 
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  float h2 = dht2.readHumidity();
  float t2 = dht2.readTemperature();
 

  if (isnan(h) || isnan(t)) {
    Serial.println("DHT22 недоступен.");
    return;
  }
  server.send(200, "html"); {
<!DOCTYPE html>
<html>
<head>
  <title>TempAndHum</title>
<meta charset="utf-8">
</head>
<body>
     <h1>SENSOR 1</h1>
     <hr>
     <center>"Temperature: "+String(t)+" " + "Humidity: "+String(h) +". "</center>
     <hr>
</body>
</html>
  }
  }

void setup() {
  WiFi.begin("xxxx", "xxxx");
  server.on("/", handleRoot);
  server.begin();
  Serial.println("DHTxx test!");
    dht.begin();

 
}
void loop() {
  server.handleClient();

}
И прежде чем "вырезать значение на html, нужно же подключить скрипт к IP самой esp, а иначе откуда он будет его вырезать и потом это значение подставить в переменную " $sensor_temperature".
Если есть где-то похожий туториал, я бы изучил, потому что спрашивать у вас по каждой команде тоже тяжело, я понимаю. Потому что я не знаю как это в php прописать.
 
Последнее редактирование:

gerkimuyda

New member
PHP:
<?php

  $sensors = array(
    array(
        'name'        => '#1 (East)',
        'address'    => 'http://192.168.100.1/',
    ),
    array(
        'name'        => '#2 (South)',
        'address'    => 'http://192.168.100.2/',
    ),
    array(
        'name'        => '#3 (West)',
        'address'    => 'http://192.168.100.3/',
    ),
    array(
        'name'        => '#4 (North)',
        'address'    => 'http://192.168.100.4/',
    ),
    array(
        'name'        => '#5 (Center)',
        'address'    => 'http://192.168.100.5/',
    ),
  );

  $db_server    =    "localhost";
  $db_username    =    "arduino";
  $db_password    =    "arduinotest";
  $db_database    =    "esp";
  $db = mysqli_connect($db_server, $db_username, $db_password, $db_database);
  if(!$db) { print "MySQL Error: ".mysqli_connect_error(); exit; }



  foreach($sensors as $num=>$sensor) {
    print "Request sensor ".($num+1)."/".count($sensors).": ".$sensor['name']." - ";
    $sensor_temperature = 'NULL';
    $sensor_humidity='NULL';

    $ctx = stream_context_create( array('http' => array('timeout' => 1) ) );
    $res = @file_get_contents($sensor['address'], 0, $ctx);

    if($res) { print "ON";
//for debug
//$res = "text<span id='temperature'>11.22</span>text<span id='humidity'>33.44</span>text";

     preg_match("/\<span id='temperature'\>(.*)\<\/span\>/imsuU", $res, $matches);
     if(!empty($matches['1'])) { $sensor_temperature = "'".mysqli_real_escape_string($db, $matches['1'])."'"; }

     preg_match("/\<span id='humidity'\>(.*)\<\/span\>/imsuU", $res, $matches);
     if(!empty($matches['1'])) { $sensor_humidity = "'".mysqli_real_escape_string($db, $matches['1'])."'"; }
    }else{ print "OFF"; }
   print " = ".$sensor_temperature.", ".$sensor_humidity.".".PHP_EOL;
   $sql  = "INSERT INTO `serenity` (`sensor`, `temperature`, `humidity`, `datetime`) ".
       "VALUES ('".mysqli_real_escape_string($db, $sensor['name'])."', ";
   $sql .= $sensor_temperature.", ".$sensor_humidity.", NOW()); ";

   mysqli_query($db,$sql);
   $error = mysqli_error($db);
   if($error) { print "MySQL Error: ".$error; exit; }
  } //foreach
print "Done.";
 

gerkimuyda

New member
Я не понимаю, как должна выглядеть функция ?
Код:
  server.send(200, "html"); {
<!DOCTYPE html>
<html>
<head>
  <title>TempAndHum</title>
<meta charset="utf-8">
</head>
<body>
     <h1>SENSOR 1</h1>
     <hr>
     <center>"Temperature: "+String(t)+" " + "Humidity: "+String(h) +". "</center>
     <hr>
</body>
</html>
  }
Код:
server.send(200, "text/html", "<!DOCTYPE html>\r\n<html><head><title>TempAndHum</title><meta charset='utf-8'></head>\r\n<body><h1>SENSOR 1</h1><hr><center>Temperature: "+String(t)+"Humidity: "+String(h) +". </center><hr></body></html>");
 

serenityLA

New member
Код:
server.send(200, "text/html", "<!DOCTYPE html>\r\n<html><head><title>TempAndHum</title><meta charset='utf-8'></head>\r\n<body><h1>SENSOR 1</h1><hr><center>Temperature: "+String(t)+"Humidity: "+String(h) +". </center><hr></body></html>");
Понял, это особенности arduino IDE так прописывать код html ?

Скрипт работает, добавляет данные в БД, но не может считать и везде ставит NULL (ну точнее пока только в первом )

У меня немножко пухнет мозг от попыток разобраться в логике кода. Это как решать уравнение не зная формул ). Скачал себе книгу learning php david sklar php 7 , буду читать походу разбирательств. Если можете по sql что-то посоветовать для образования, буду признателен.
 
Последнее редактирование:
  • Like
Реакции: kab
Сверху Снизу