ESP32/ESP8266: отправка данных на LAMP-сервер Raspberry Pi

В этом проекте вы создадите клиент на ESP32 или ESP8266, который выполняет HTTP POST-запрос к LAMP-серверу Raspberry Pi (L inux, A pache, M ySQL, P HP). На Raspberry Pi будет работать PHP-скрипт для вставки данных (показаний датчиков) в базу данных MySQL.

ESP32 ESP8266 Вставка данных в базу данных MySQL на Raspberry Pi

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

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

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

Для создания этого проекта вы будете использовать следующие технологии:

  • Запуск LAMP-сервера на Raspberry Pi

  • ESP32 или ESP8266, запрограммированные в Arduino IDE

  • PHP-скрипт для вставки данных в MySQL и отображения их на веб-странице

  • База данных MySQL для хранения показаний

0. Необходимые условия

Прежде чем продолжить этот урок:

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

После того как ваша плата Raspberry Pi будет подготовлена с ОС Raspbian и LAMP-сервером, вы можете продолжить этот урок.

1. Размещение PHP-приложения и базы данных MySQL – Raspberry Pi

Цель этого проекта – иметь Raspberry Pi с работающим LAMP-сервером, который позволяет хранить показания датчиков с ESP32 или ESP8266. Вы можете визуализировать показания из любого браузера в вашей локальной сети.

Вот общий обзор:

Размещение PHP-приложения и базы данных MySQL на Raspberry Pi для публикации показаний датчиков ESP32 или ESP8266

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

2. Подготовка базы данных MySQL

После установки LAMP-сервера и phpMyAdmin на Raspberry Pi, вы можете войти в phpMyAdmin. После этого выполните следующие шаги для создания базы данных и SQL-таблицы.

Откройте браузер и введите http://IP-адрес-вашего-Raspberry-Pi/phpmyadmin – вы должны увидеть страницу входа веб-интерфейса phpMyAdmin.

Raspberry Pi страница входа phpMyAdmin

После входа вы должны увидеть похожую страницу:

Raspberry Pi phpMyAdmin локальная база данных MySQL

Создание базы данных

1. Выберите меню «Databases» вверху, заполните поля «Create database»:

  • esp_data

  • utf8mb4_general_ci

Затем нажмите кнопку Create:

Raspberry Pi phpMyAdmin создание новой базы данных

Вот и всё! Ваша новая база данных успешно создана. Теперь сохраните имя базы данных, оно понадобится позже:

  • Имя базы данных: esp_data

Создание SQL-таблицы

После создания базы данных выберите в левой боковой панели имя вашей базы данных esp_data:

Raspberry Pi phpMyAdmin открытие новой базы данных

Важно: убедитесь, что вы открыли базу данных esp_data. Затем нажмите вкладку SQL. Если вы не будете точно следовать этим шагам и выполните SQL-запрос, вы можете создать таблицу в неправильной базе данных.

Скопируйте SQL-запрос из следующего фрагмента:

CREATE TABLE SensorData (
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    sensor VARCHAR(30) NOT NULL,
    location VARCHAR(30) NOT NULL,
    value1 VARCHAR(10),
    value2 VARCHAR(10),
    value3 VARCHAR(10),
    reading_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)

Просмотреть исходный код

Откройте вкладку «SQL», вставьте его в поле SQL-запроса (выделено красным прямоугольником) и нажмите кнопку Go, чтобы создать таблицу:

Raspberry Pi phpMyAdmin выполнение SQL-запроса

Если таблица создана успешно, должно появиться следующее:

Raspberry Pi phpMyAdmin SQL-таблица создана

После этого вы должны увидеть вашу вновь созданную таблицу SensorData в базе данных esp_data, как показано на рисунке ниже:

Raspberry Pi phpMyAdmin пустая созданная таблица

3. PHP-скрипт HTTP POST – вставка данных в базу данных MySQL

В этом разделе мы создадим PHP-скрипт, который отвечает за получение входящих запросов от ESP32 или ESP8266 и вставку данных в базу данных MySQL.

Вы можете выполнять следующие команды на Raspberry Pi, настроенном как настольный компьютер, или используя SSH-подключение.

Если вы подключены к Raspberry Pi через SSH, введите следующую команду для создания файла в каталоге /var/www/html:

pi@raspberrypi:~ $ nano /var/www/html/post-esp-data.php
Raspberry Pi сохранение файла post-esp-data.php

Примечание: если вы следуете этому уроку и не знакомы с PHP или MySQL, рекомендуем создать именно эти файлы. В противном случае вам придётся изменить скетч ESP с другими URL-путями.

Скопируйте следующий PHP-скрипт в только что созданный файл (post-esp-data.php):

<?php

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

$servername = "localhost";

// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";

// Keep this API Key value to be compatible with the ESP32 code provided in the project page.
// If you change this value, the ESP32 sketch needs to match
$api_key_value = "tPmAT5Ab3j7F9";

$api_key= $sensor = $location = $value1 = $value2 = $value3 = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $api_key = test_input($_POST["api_key"]);
    if($api_key == $api_key_value) {
        $sensor = test_input($_POST["sensor"]);
        $location = test_input($_POST["location"]);
        $value1 = test_input($_POST["value1"]);
        $value2 = test_input($_POST["value2"]);
        $value3 = test_input($_POST["value3"]);

        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }

        $sql = "INSERT INTO SensorData (sensor, location, value1, value2, value3)
        VALUES ('" . $sensor . "', '" . $location . "', '" . $value1 . "', '" . $value2 . "', '" . $value3 . "')";

        if ($conn->query($sql) === TRUE) {
            echo "New record created successfully";
        }
        else {
            echo "Error: " . $sql . "<br>" . $conn->error;
        }

        $conn->close();
    }
    else {
        echo "Wrong API Key provided.";
    }

}
else {
    echo "No data posted with HTTP POST.";
}

function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}

Просмотреть исходный код

Перед сохранением файла вам необходимо изменить переменные $dbname, $username и $password на ваши собственные данные:

// Your Database name
$dbname = "esp_data";
// Your Database user
$username = "root";
// Your Database user password
$password = "YOUR_USER_PASSWORD";

После добавления имени базы данных, имени пользователя и пароля сохраните файл (Ctrl+X, y и клавиша Enter) и продолжайте этот урок.

Raspberry Pi сохранённый файл post-esp-data.php

Если вы попробуете получить доступ к IP-адресу вашего Raspberry Pi по следующему URL-пути, вы увидите следующее:

http://IP-адрес-вашего-Raspberry-Pi/post-esp-data.php
ESP32 ESP8266 PHP страница сохранения показаний в базу данных MySQL Raspberry Pi

4. PHP-скрипт – отображение содержимого базы данных

Создайте ещё один PHP-файл в каталоге /var/www/html, который будет отображать всё содержимое базы данных на веб-странице. Назовите ваш новый файл: esp-data.php

pi@raspberrypi:~ $ nano /var/www/html/esp-data.php
Raspberry Pi сохранение файла esp-data.php

Отредактируйте только что созданный файл (esp-data.php) и скопируйте следующий PHP-скрипт:

<!DOCTYPE html>
<html><body>
<?php
/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

$servername = "localhost";

// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT id, sensor, location, value1, value2, value3, reading_time FROM SensorData ORDER BY id DESC";

echo '<table cellspacing="5" cellpadding="5">
      <tr>
        <td>ID</td>
        <td>Sensor</td>
        <td>Location</td>
        <td>Value 1</td>
        <td>Value 2</td>
        <td>Value 3</td>
        <td>Timestamp</td>
      </tr>';

if ($result = $conn->query($sql)) {
    while ($row = $result->fetch_assoc()) {
        $row_id = $row["id"];
        $row_sensor = $row["sensor"];
        $row_location = $row["location"];
        $row_value1 = $row["value1"];
        $row_value2 = $row["value2"];
        $row_value3 = $row["value3"];
        $row_reading_time = $row["reading_time"];
        // Uncomment to set timezone to - 1 hour (you can change 1 to any number)
        //$row_reading_time = date("Y-m-d H:i:s", strtotime("$row_reading_time - 1 hours"));

        // Uncomment to set timezone to + 4 hours (you can change 4 to any number)
        //$row_reading_time = date("Y-m-d H:i:s", strtotime("$row_reading_time + 4 hours"));

        echo '<tr>
                <td>' . $row_id . '</td>
                <td>' . $row_sensor . '</td>
                <td>' . $row_location . '</td>
                <td>' . $row_value1 . '</td>
                <td>' . $row_value2 . '</td>
                <td>' . $row_value3 . '</td>
                <td>' . $row_reading_time . '</td>
              </tr>';
    }
    $result->free();
}

$conn->close();
?>
</table>
</body>
</html>

Просмотреть исходный код

Добавьте $dbname, $username и $password:

// Your Database name
$dbname = "esp_data";
// Your Database user
$username = "root";
// Your Database user password
$password = "YOUR_USER_PASSWORD";

Сохраните файл (Ctrl+X, y и клавиша Enter) и продолжайте этот проект.

Raspberry Pi сохранённый файл esp-data.php

Если вы попробуете получить доступ к IP-адресу вашего Raspberry Pi по следующему URL-пути, вы увидите следующее:

http://IP-адрес-вашего-Raspberry-Pi/esp-data.php
ESP32 ESP8266 PHP страница просмотра показаний температуры влажности давления BME280

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

5. Подготовка ESP32 или ESP8266

Этот проект совместим как с платами ESP32, так и с ESP8266. Вам нужно только собрать простую схему и загрузить предоставленный скетч для вставки температуры, влажности, давления и других данных в базу данных каждые 30 секунд.

Необходимые компоненты

Для этого примера мы будем получать показания с датчика BME280. Вот список компонентов, необходимых для сборки схемы этого проекта:

Схемы подключения

Модуль датчика BME280, который мы используем, взаимодействует через протокол связи I2C, поэтому вам нужно подключить его к выводам I2C ESP32 или ESP8266.

Подключение BME280 к ESP32

Выводы I2C ESP32:

  • GPIO 22: SCL (SCK)

  • GPIO 21: SDA (SDI)

Итак, соберите вашу схему, как показано на следующей схематической диаграмме (прочитайте полное руководство по ESP32 с BME280).

Подключение BME280 к ESP32

Рекомендуемое чтение: Справочное руководство по выводам ESP32

Подключение BME280 к ESP8266

Выводы I2C ESP8266:

  • GPIO 5 (D1): SCL (SCK)

  • GPIO 4 (D2): SDA (SDI)

Соберите вашу схему, как показано на следующей схематической диаграмме, если вы используете плату ESP8266 (прочитайте полное руководство по ESP8266 с BME280).

Подключение BME280 к ESP8266

Рекомендуемое чтение: Справочное руководство по выводам ESP8266

Код ESP32/ESP8266

Мы будем программировать ESP32/ESP8266 с помощью Arduino IDE, поэтому у вас должно быть установлено дополнение ESP32/ESP8266 в вашей Arduino IDE. Следуйте одному из следующих уроков в зависимости от используемой платы:

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

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-mysql-database-php/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

*/

#ifdef ESP32
  #include <WiFi.h>
  #include <HTTPClient.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESP8266HTTPClient.h>
  #include <WiFiClient.h>
#endif

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// REPLACE with your Domain name and URL path or IP address with path
const char* serverName = "http://example.com/post-esp-data.php";

// Keep this API Key value to be compatible with the PHP code provided in the project page.
// If you change the apiKeyValue value, the PHP file /post-esp-data.php also needs to have the same key
String apiKeyValue = "tPmAT5Ab3j7F9";

String sensorName = "BME280";
String sensorLocation = "Office";

/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme;  // I2C
//Adafruit_BME280 bme(BME_CS);  // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);  // software SPI

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  // (you can also pass in a Wire library object like &Wire2)
  bool status = bme.begin(0x76);
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring or change I2C address!");
    while (1);
  }
}

void loop() {
  //Check WiFi connection status
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;

    // Your Domain name with URL path or IP address with path
    http.begin(client, serverName);

    // Specify content-type header
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");

    // Prepare your HTTP POST request data
    String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
                          + "&location=" + sensorLocation + "&value1=" + String(bme.readTemperature())
                          + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);

    // You can comment the httpRequestData variable above
    // then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
    //String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BME280&location=Office&value1=24.75&value2=49.54&value3=1005.14";

    // Send HTTP POST request
    int httpResponseCode = http.POST(httpRequestData);

    // If you need an HTTP request with a content type: text/plain
    //http.addHeader("Content-Type", "text/plain");
    //int httpResponseCode = http.POST("Hello, World!");

    // If you need an HTTP request with a content type: application/json, use the following:
    //http.addHeader("Content-Type", "application/json");
    //int httpResponseCode = http.POST("{\"value1\":\"19\",\"value2\":\"67\",\"value3\":\"78\"}");

    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
  }
  else {
    Serial.println("WiFi Disconnected");
  }
  //Send an HTTP POST request every 30 seconds
  delay(30000);
}

Просмотреть исходный код

Настройка сетевых учётных данных

Вам нужно изменить следующие строки, указав ваши сетевые учётные данные: SSID и пароль. Код хорошо прокомментирован в местах, где нужно внести изменения.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Настройка serverName

Вам также нужно ввести IP-адрес вашего Raspberry Pi, чтобы ESP публиковал показания на ваш LAMP-сервер.

const char* serverName = "http://IP-адрес-вашего-Raspberry-Pi/post-esp-data.php";

Например:

const char* serverName = "http://192.168.1.86/post-esp-data.php";

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

Как работает код

Этот проект уже достаточно объёмный, поэтому мы не будем подробно рассматривать, как работает код, но вот краткое резюме:

  • Импорт всех библиотек для работы (будут импортированы библиотеки ESP32 или ESP8266 в зависимости от выбранной платы в вашей Arduino IDE)

  • Настройка переменных, которые вы можете изменить (apiKeyValue, sensorName, sensorLocation)

  • apiKeyValue – это просто случайная строка, которую вы можете изменить. Она используется в целях безопасности, чтобы только тот, кто знает ваш API-ключ, мог публиковать данные в вашу базу данных

  • Инициализация последовательной связи для целей отладки

  • Установка Wi-Fi соединения с вашим маршрутизатором

  • Инициализация BME280 для получения показаний

Затем, в loop() происходит фактический HTTP POST-запрос каждые 30 секунд с последними показаниями BME280:

// Your Domain name with URL path or IP address with path
http.begin(serverName);

// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");

// Prepare your HTTP POST request data
String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
                      + "&location=" + sensorLocation + "&value1=" + String(bme.readTemperature())
                      + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";

int httpResponseCode = http.POST(httpRequestData);

Вы можете закомментировать переменную httpRequestData выше, которая объединяет все показания BME280, и использовать переменную httpRequestData ниже для целей тестирования:

String httpRequestData = "api_key=tPmAT5Ab3j7F9&sensor=BME280&location=Office&value1=24.75&value2=49.54&value3=1005.14";

Демонстрация

После выполнения всех шагов дайте вашей плате ESP собрать несколько показаний и опубликовать их на ваш сервер.

ESP32 BME280 Arduino IDE MySQL

Если всё правильно, вот что вы должны увидеть в мониторе последовательного порта Arduino IDE:

ESP32 ESP8266 публикация показаний в базу данных MySQL Raspberry Pi

Если вы откроете IP-адрес вашего Raspberry Pi по URL-пути /esp-data.php:

http://IP-адрес-вашего-Raspberry-Pi/esp-data.php

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

Raspberry Pi PHP MySQL просмотр показаний ESP32 ESP8266

Вы также можете зайти в phpMyAdmin для управления данными, хранящимися в таблице SensorData. Вы можете удалять их, редактировать и т.д.

Raspberry Pi phpMyAdmin таблица с опубликованными показаниями ESP32 ESP8266

Заключение

В этом уроке вы узнали, как публиковать данные датчиков в базу данных на вашем собственном локальном LAMP-сервере Raspberry Pi.

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

Вам также может понравиться:

Надеемся, вам понравился этот проект. Если у вас есть вопросы, оставьте комментарий ниже, и мы постараемся ответить.

Если вам нравится ESP32, вы можете рассмотреть возможность записаться на наш курс «Изучите ESP32 с Arduino IDE». Вы также можете получить доступ к нашим бесплатным ресурсам по ESP32 здесь.

Спасибо за чтение.