上次我们讲述了怎么样搭建LAMP,然而怎么样应用到实际领域中呢?有人说搭建博客,没错我的博客也是这么来的,这也是LAMP的一种典型实例,可是这种实例烂大街,都不香了 :huaji: .这次我们利用单片机将传感器数据直接推送到树莓派搭建的LANMP服务器中.在这个项目中,您将构建一个ESP32或ESP8266客户端,树莓派 Pi LAMP服务器(Linux,Apache,MySQL,PHP)发出HTTP POST请求。 树莓派 Pi具有一个PHP脚本,可将数据(传感器读数)插入MySQL数据库。

我们这次做一个网页,显示存储在数据库中的传感器读数,时间戳和其他信息。然后,从网络中的任何浏览器本地查看数据。
举例来说,用连接到ESP上的BME280传感器。您可以这里提供的代码,以从其他传感器发送读数或使用多个开发板。

要构建此项目,您需要的事项:

  • 在树莓派上上运行的LAMP服务器
  • 使用Arduino IDE编程的ESP32或ESP8266(也可以是PlatformIO)
  • PHP脚本将数据插入MySQL并显示在网页上
  • MySQL数据库存储读数

先决条件

在继续本教程之前你需要准备的只是:

  • 熟悉树莓派(不然你都不知道我说啥)
  • 已安装Raspbian或Raspbian Lite操作系统
  • 您还需要以下硬件:
    • Raspberry Pi board – read Best Raspberry Pi Starter Kits
    • MicroSD Card – 16GB Class10
    • Raspberry Pi Power Supply (5V 2.5A)
    • 要在树莓派上准备LAMP服务器,请遵循以下步骤:安装Apache + MySQL + PHP(LAMP服务器)

在使用Raspbian和LAMP服务器准备好树莓派开发板之后,就可以继续往下看了。

托管PHP应用程序和MySQL数据库树莓派

目标是让树莓派运行LAMP服务器,服务器允许您存储来自ESP32或ESP8266的传感器读数。您可以可视化来自本地网络中任何读数。

你还可以通过外网访问,不过这都是后话,新手还是先弄好本地访问再说.

准备MySQL数据库

按照以下步骤创建数据库和SQL表,打开浏览器并输入http//你的树莓派IP/phpmyadmin),您应该会看到phpMyAdmin Web界面的登录页面.

登录后,您应该会看到类似的页面:

创建数据库

  1. 选择顶部的“数据库”菜单,完成“创建数据库”字段:
    • esp_data
    • utf8mb4_general_ci

然后,按创建按钮:

新数据库已成功创建。现在,记住您的数据库名称,因为以后需要,数据库名称:esp_data

创建一个SQL表

创建数据库后,在左侧边栏中选择数据库名称esp_data

重要提示:请确保您已打开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查询字段中(以红色矩形突出显示),然后按“执行”按钮创建表:

如果成功创建了表,则应显示以下内容:

之后,您应该在esp_data数据库中看到新创建的表SensorData,如下图所示:

PHP脚本HTTP POST-将数据插入MySQL数据库

在本部分中,我们将创建一个PHP脚本,该脚本负责接收来自ESP32或ESP8266的传入请求,并将数据插入MySQL数据库。您可以在设置为台式计算机的树莓派上运行下一个命令,也可以使用SSH连接。

nano /var/www/html/post-esp-data.php

注意:如果您正在阅读本教程,并且对PHP或MySQL不熟悉,建议您创建这些确切的文件。否则,您需要修改随其他网址路径.

将以下PHP脚本复制到新创建的文件(post-esp-data.php):

<?php

$servername = "localhost";

$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";

$username = "REPLACE_WITH_YOUR_USERNAME";

$password = "REPLACE_WITH_YOUR_PASSWORD";

$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"]);

        $conn = new mysqli($servername, $username, $password, $dbname);

        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变量:


$dbname = "esp_data";

$username = "root";

$password = "YOUR_USER_PASSWORD";

添加数据库名称,用户名和密码后,保存文件(Ctrl + X,y和Enter键)并继续本教程。

如果您尝试在下一个URL路径中访问树莓派的IP地址,则会看到以下内容:
http://You-Raspberry-Pi-IP-Address/post-esp-data.php

PHP脚本–显示数据库内容

/var/www/html目录中创建另一个PHP文件,该文件将在网页中显示所有数据库内容。命名您的新文件:esp-data.php

nano /var/www/html/esp-data.php

编辑新创建的文件(esp-data.php)并复制以下PHP脚本:

<!DOCTYPE html>
<html><body>
<?php

$servername = "localhost";

$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";

$username = "REPLACE_WITH_YOUR_USERNAME";

$password = "REPLACE_WITH_YOUR_PASSWORD";

$conn = new mysqli($servername, $username, $password, $dbname);

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"];

        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>

保存文件.
如果您尝试通过以下URL路径访问树莓派地址,则会看到以下内容:

5.准备您的ESP32或ESP8266
该项目与ESP32和ESP8266开发板均都兼容。您只需要组装一个简单的电路,实例代码在每30秒将温度,湿度,压力等添加到您的数据库中

所需材料

在此示例中,我们将从BME280传感器获取传感器读数。以下是为该项目构建电路所需的零件清单:

  • ESP32
  • 或者ESP8266
  • BME280传感器模块
  • 面包板

原理图

BME280传感器模块通过I2C通信协议进行通信,因此您需要将其连接到ESP32或ESP8266 I2C引脚。

BME280连线至ESP32

  • GPIO 22: SCL (SCK)
  • GPIO 21: SDA (SDI)

BME280连线至ESP8266

ESP8266 I2C引脚为:

  • GPIO 5 (D1): SCL (SCK)
  • GPIO 4 (D2): SDA (SDI)

ESP32/ESP8266 代码

#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>

const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* serverName = "http://example.com/post-esp-data.php";

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());

  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() {

  if(WiFi.status()== WL_CONNECTED){
    HTTPClient http;

    http.begin(serverName);

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

    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);

    int httpResponseCode = http.POST(httpRequestData);

    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    http.end();
  }
  else {
    Serial.println("WiFi Disconnected");
  }
  delay(30000);  
}

设置您的网络凭证

您需要使用网络凭据修改以下行:SSID和密码。该代码很好地注释了您应该在哪里进行更改。

const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

设置您的服务器名

const char* serverName = "http://你的树莓派IP/post-esp-data.php";

将代码上传到板上。它应立即在ESP32或ESP8266板上运行了

代码解析

项目已经很长了,因此我们不会详细介绍代码的工作原理,但是这里有一个简短的摘要:

  • 设置您可能想要更改的变量(apiKeyValuesensorNamesensorLocation
  • apiKeyValue只是可以修改的随机字符串。出于安全原因使用它,因此只有知道您的API密钥的任何人才能将数据发布到您的数据库
  • 初始化串行通信以进行调试
  • 与路由器建立Wi-Fi连接
  • 初始化BME280以获取读数

然后,在loop()函数中,您实际上是每30秒发出一次HTTP POST请求,并获取最新的BME280读数:

// 你的域名或者IP地址
http.begin(serverName);

// 指定内容类型标题
http.addHeader("Content-Type", "application/x-www-form-urlencoded");

// 准备您的HTTP POST请求数据
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);

您可以注释上面连接所有BME280读数的httpRequestData变量,并使用下面的httpRequestData变量进行测试:

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

示范

如果一切正确,那么您应该在Arduino IDE串行监视器中看到以下内容:

如果您在此URL路径/esp-data.php中打开树莓派的IP地址:

http://你的树莓派IP/esp-data.php

您应该看到数据库中存储的所有读数。刷新网页以查看最新读数:

您也可以转到phpMyAdmin来管理存储在SensorData表中的数据。您可以删除,编辑等等.

总括

传感器数据发布到您自己的本地树莓派LAMP服务器中的数据库中.这里写的示例代码尽可能简单,只是为了以便您了解所有基本工作原理。你可以用不同的传感器,让读书从多个ESP板发布数据.在理解了此示例后,您可以更改表格的外观之类,如下图:



往下滑,显示更多内容