dht22 отправлять данные в базу данных и показывать на веб-сервере

Alex277
Offline
Зарегистрирован: 20.01.2021

Привет! У меня есть код, который отправляет данные dht22 в базу данных mysql в определенное время с помощью ds3231:

#include <SPI.h>
#include <Ethernet.h>
#include "DHT.h"
#include <TimeLib.h>
#include <TimeAlarms.h>
#include <Wire.h>
#include <DS1307RTC.h>
#define DHTPIN 7
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //Newer Ethernet shields have a MAC address printed on a sticker on the shield
IPAddress server(192, 168, 7, 1); //IPv4 address
EthernetClient client;

void setup() {
  Serial.begin(9600);
  // wait for Arduino Serial Monitor
  while (!Serial) ;

  // get and set the time from the RTC
  setSyncProvider(RTC.get);
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");

  // to test your project, you can set the time manually
  //setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011

  // create the alarms, to trigger functions at specific times
  Alarm.alarmRepeat(10, 25, 0, MorningAlarm);
  Alarm.alarmRepeat(10, 25, 30, EveningAlarm);

  Ethernet.begin(mac);
  dht.begin();
}

void loop() {
  digitalClockDisplay();
  // wait one second between each clock display in serial monitor
  Alarm.delay(1000);
}
        
void AlaramFunc() {
  int idSensor = 1;
  float hum = dht.readHumidity();
  float temp = dht.readTemperature();
  float fah = dht.readTemperature(true);
  float heat_index = dht.computeHeatIndex(fah, hum);
  float heat_indexC = dht.convertFtoC(heat_index);

  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.print("GET /data.php?");
    client.print("temperature=");
    client.print(temp);
    client.print("&humidity=");
    client.print(hum);
    client.print("&heat_index=");
    client.print(heat_indexC);
    client.print("&idSensor=");
    client.print(idSensor);
    client.println(" HTTP/1.1");
    client.println("Host: 192.168.7.1");
    client.println("Connection: close");
    client.println();

    Serial.print("GET /data.php?");
    Serial.print("temperature=");
    Serial.print(temp);
    Serial.print("&humidity=");
    Serial.print(hum);
    Serial.print("&heat_index=");
    Serial.print(heat_indexC);
    Serial.print("&idSensor=");
    Serial.print(idSensor);
    Serial.println(" HTTP/1.1");
    client.stop(); //Closing the connection
  } else {
    //if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void MorningAlarm() {
  AlaramFunc();
}

void EveningAlarm() {
  AlaramFunc();
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}
void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Я пытаюсь объединить свой код с кодом из этого примера, чтобы также показывать текущую температуру и влажность. Но код не работает полностью. Он показывает данные на веб-сервере, но не может подключиться (connection failed на serial monitor) для отправки данных в БД. Что нужно исправить?

#include <SPI.h>
#include <Ethernet.h>
#include "DHT.h"
#include <TimeLib.h>
#include <TimeAlarms.h>
#include <Wire.h>
#include <DS1307RTC.h>
#define DHTPIN 7
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //Newer Ethernet shields have a MAC address printed on a sticker on the shield
IPAddress server(192, 168, 7, 1); //IPv4 address
EthernetClient client;

IPAddress ip(192, 168, 1, 99);
EthernetServer server1(80);

void setup() {
  Serial.begin(9600);
  // wait for Arduino Serial Monitor
  while (!Serial) ;

  // get and set the time from the RTC
  setSyncProvider(RTC.get);
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");

  // to test your project, you can set the time manually
  //setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011

  // create the alarms, to trigger functions at specific times
  Alarm.alarmRepeat(15, 27, 0, MorningAlarm);
  Alarm.alarmRepeat(15, 28, 0, EveningAlarm);

  Ethernet.begin(mac, ip);
  dht.begin();
  server1.begin();
}

void loop() {
  digitalClockDisplay();
  // wait one second between each clock display in serial monitor
  Alarm.delay(1000);
  float h = dht.readHumidity( );
  float t = dht.readTemperature( );
  EthernetClient client = server1.available();
  if (client)
    {
      boolean currentLineIsBlank = true;
      while (client.connected ( ) )
        {
          if (client.available ( ) )
            {
              char character = client.read ( );
              Serial.write(character);
              if (character == '\n' && currentLineIsBlank)
                {
                  client.println ("HTTP/1.1 200 OK");
                  client.println ("Content-Type: text/html");
                  client.println ("Connection: close");
                  client.println ("Refresh: 5");
                  client.println ( );
                  client.println ("<!DOCTYPE HTML>");
                  client.println ("<html>");
                  client.print ("<Title>Arduino Ethernet Webserver </Title>");
                  client.print ("<h1>Arduino Ethernet Shield Webserver </h1>");
                  client.print ("<h4>Temperature in C: ");
                  client.print (t);client.print("C");
                  client.print ("</h4><h4>Humidity: ");
                  client.print (h);client.print("%");
                  client.println ("<br />");
                  client.println ("</html>");
                  break;
                }
                 
                if ( character == '\n')
                  {
                    currentLineIsBlank = true;
                  }
                else if (character != '\r')
                  {
                    currentLineIsBlank = false;
            }
        }
    }
    delay(1);
    client.stop();
  }
}

  void AlaramFunc() {
  int idSensor = 1;
  float hum = dht.readHumidity();
  float temp = dht.readTemperature();
  float fah = dht.readTemperature(true);
  float heat_index = dht.computeHeatIndex(fah, hum);
  float heat_indexC = dht.convertFtoC(heat_index);

  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.print("GET /data.php?");
    client.print("temperature=");
    client.print(temp);
    client.print("&humidity=");
    client.print(hum);
    client.print("&heat_index=");
    client.print(heat_indexC);
    client.print("&idSensor=");
    client.print(idSensor);
    client.println(" HTTP/1.1");
    client.println("Host: 192.168.7.1");
    client.println("Connection: close");
    client.println();

    Serial.print("GET /data.php?");
    Serial.print("temperature=");
    Serial.print(temp);
    Serial.print("&humidity=");
    Serial.print(hum);
    Serial.print("&heat_index=");
    Serial.print(heat_indexC);
    Serial.print("&idSensor=");
    Serial.print(idSensor);
    Serial.println(" HTTP/1.1");
    client.stop(); //Closing the connection
  } else {
    //if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void MorningAlarm() {
  AlaramFunc();
}

void EveningAlarm() {
  AlaramFunc();
}

void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}
void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

 

b707
Offline
Зарегистрирован: 26.05.2017

код не читал, но в целом к задаче вы подходите неверно. зачем дублировать и посылать данные ардуиной через сеть дважды - сначала на в БД, а потом на сервер. Общение с сетью для ардуины и так сложно...

Достаточно отсылать данные в Mysql, а веб-сервер пусть берет их из базы сам, без участия ардуины.

Alex277
Offline
Зарегистрирован: 20.01.2021

Не хотелось бы переполнять базу большим количеством записей. Сейчас как у меня в коде в день добавляются только два значения, а так надо будет например передавать данные датчика каждые несколько секунд.

b707
Offline
Зарегистрирован: 26.05.2017

Alex277 пишет:

Не хотелось бы переполнять базу большим количеством записей. Сейчас как у меня в коде в день добавляются только два значения, а так надо будет например передавать данные датчика каждые несколько секунд.

а нафига тогда вообще БД. если не для хранения записей?

Или вы хотите, чтобы сервер у вас в реальном времени подключался к ардуине и получал данные? - имхо, это неверный подход, быть HTTP-сервером ардуине еще труднее. чем просто слать по сети

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Поверьте, куда приятнее и удобнее оперировать не "голыми" данными, а данными в СУБД.

Alex277 пишет:

Не хотелось бы переполнять базу большим количеством записей. Сейчас как у меня в коде в день добавляются только два значения, а так надо будет например передавать данные датчика каждые несколько секунд.

Зачем так часто передавать данные на web-сервер? Сохранили в промежуточной переменной прошлое измерение и смотрите - "а сейчас поменялось может что?" и если "ой, действительно поменялось" - шлете эти данные в БД. Если у Вас там не турбонагрев с турбоохлаждением, то данные в БД раз в несколько минут/десятков минут будут "падать", а то и часов (если температура стабильна). А вот вычитывать данные из СУБД web-сервером можно и каждую минуту, ничего страшного. :)

sadman41
Offline
Зарегистрирован: 19.10.2016

Метод "передача по изменению" имеет неприятный дефект - она не позволяет понять - работает ли устройство снятия параметров окружающей среды в текущий момент.

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:
Метод "передача по изменению" имеет неприятный дефект - она не позволяет понять - работает ли устройство снятия параметров окружающей среды в текущий момент.

можно комбинировать. Передавать данные в базу каждые 5 минут (полчаса / 6 часов...) или чаще, если данные изменились более чем на градус...

другой вопрос, что с данными, неравномерно распределенными по времени - неудобно работать...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

sadman41 пишет:
Метод "передача по изменению" имеет неприятный дефект - она не позволяет понять - работает ли устройство снятия параметров окружающей среды в текущий момент.

Это легко решается отправкой "раз в "определенный" интервал времени" данных что всё ОК (к примеру, раз в 15 минут/1 час или как Вам нужно), можно и отправлять в выше указанное время текущие параметры. Но лично я бы не стал так делать, проще слать отдельные данные в отдельную таблицу о состоянии устройства (или датчиков устройства).  Как только в нужный интервал web-сервер не получил данные - АЛЯРМ! Что-то случилось.

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

другой вопрос, что с данными, неравномерно распределенными по времени - неудобно работать...


Это тоже. Если делать выборку в базе по диапазону времени, то концы графика могут оказаться неопределенными, если таймштампы значений метрики не находятся вблизи границ запрашиваемого периода.

sadman41
Offline
Зарегистрирован: 19.10.2016

BOOM пишет:

Это легко решается отправкой "раз в "определенный" интервал времени" данных что всё ОК (к примеру, раз в 15 минут/1 час или как Вам нужно),


Лишняя метрика, больше затрат на сбор/администрирование. Продуктивней основную сразу собирать периодически.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Вы имеете ввиду слать, к примеру, каждые 5 минут данные вне зависимости от того изменились они или нет? Верно я понял?

Я к тому все выше писал, что как ТС писал "каждые несколько секунд" - это при каждом опросе датчика получается. Это очень часто и не нужно такого, если только действительно в турборежиме что-то греется/охлаждается. Но в таком случае нужно что-то более интерактивное, чем web-интерфейс.

sadman41
Offline
Зарегистрирован: 19.10.2016

1/5/10/N мин/сек - как того требует скорость реагирования на критические значения метрики.

Если у пользователя имеются экономические или технологические обоснования применять периодичность в "несколько секунд" - она и должна быть использована. Абстрактной "наилучшей" периодичности нет.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Это же не народный мониторинг, где надо слать не чаще раз в пять минут, для себя установил интервал минута, после полгода накопления почистил базу из-за ненужности данных, критерий - срок хранения, а MYSQL легко держит десятки миллионов записей

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

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

добавлю свои 5 коп - у меня датчик шлет данные каждую минуту, контроллер печки управляет по ним обогревом. А в БД данные сливаются раз 10 мин, ибо чаще незачем

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а я, если температура не изменилась, а я мерию в целых, поэтому система достаточно инерционная, данные тупо отбрасываю.  Если ничего не изменилось, то и решение принимать незачем. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016