基于ESP32/ESP8266与LAMP栈构建低成本分布式物联网传感系统 1. 项目概述用ESP构建你自己的分布式传感云几年前当我们需要在厂区部署一套环境监测系统时面对动辄上万的工业网关和复杂的组网协议我就在想有没有一种更轻量、更灵活且成本极低的方式直到我开始深度折腾ESP8266和ESP32这两款芯片答案才逐渐清晰。它们不仅仅是简单的Wi-Fi模块更是构建分布式、低功耗物联网数据采集节点的绝佳基石。这个项目的核心就是利用这些廉价的硬件搭建一个完全由你掌控的私有“云”系统让遍布各处的传感器数据都能自动、可靠地汇聚到你自己的中心数据库里。想象一下在整个校园或大型厂区内你部署了数十个甚至上百个小小的数据采集点。每个点都由一块ESP板子、几节电池和几个传感器构成。它们像“数字蒲公英”一样散落在各个角落自动寻找并连接可用的Wi-Fi热点定时醒来采集温度、湿度、光照、气体浓度等数据然后通过HTTP协议将数据“投递”到远端的服务器写入MySQL数据库之后便进入深度睡眠以节省电量。服务器端你可以用任何熟悉的工具比如PHPChartDirector将数据实时可视化。整套系统的单点硬件成本可以控制在50元人民币以内而数据主权和隐私性则完全掌握在你手中。这不仅仅是“物联网”更像是为你特定场景量身定制的“神经末梢网络”。2. 核心架构与设计思路拆解2.1 为什么是ESP32/ESP8266 PHP/MySQL组合这个架构的选择背后是成本、复杂度、可靠性和可控性之间的平衡。市面上有成熟的物联网平台如Thingspeak、Blynk但它们存在数据隐私、网络延迟、服务依赖和定制化限制等问题。而使用树莓派等单板计算机作为每个节点则存在功耗高通常2W、成本高300元、系统复杂需维护完整Linux系统且长期运行稳定性挑战更大的缺点。ESP系列芯片的杀手锏在于其极低的功耗深度睡眠模式下电流可低至10μA、内置的Wi-Fi/BLE功能、低廉的价格ESP8266约20元ESP32约40元以及Arduino生态带来的开发便利性。它们天生就是为这种间歇性工作的传感节点设计的。然而ESP直接与MySQL数据库对话并不容易。虽然存在一些MySQL客户端库但在Wi-Fi环境下其稳定性和兼容性往往不佳。因此本项目采用了一个非常巧妙且稳定的“中间层”方案让ESP通过HTTP协议与一个简单的PHP脚本通信再由这个PHP脚本执行数据库插入操作。这样ESP端只需要使用其稳定可靠的HTTPClient库而所有复杂的SQL逻辑、连接池管理和安全校验都放在了服务器端的PHP脚本中。这种职责分离极大地提高了整个系统的鲁棒性和可维护性。2.2 系统整体工作流程整个系统的数据流可以清晰地分为四个层次传感层由ESP32/ESP8266开发板连接各类传感器如DHT22温湿度、MQ系列气体传感器、光照传感器等构成。它们负责物理信号的采集和初步数字化。网络传输层ESP模块在唤醒后连接预设或扫描到的可用Wi-Fi网络通过HTTP POST请求将传感器数据打包发送至指定的服务器URL。服务器逻辑层运行在Apache/Nginx服务器上的PHP脚本如data_receiver.php接收HTTP请求解析POST参数进行安全验证如密钥校验然后构造SQL语句将数据插入到MySQL数据库的对应表中。数据存储与展示层MySQL数据库持久化存储所有时序数据。用户可以通过另一组PHP网页利用ChartDirector等图表库实时查询并可视化这些数据生成曲线图、仪表盘等。这种架构的优势在于扩展性极强。增加一个新的监测点几乎只需要在服务器数据库新建一张表并部署一块烧录了对应采集程序的ESP设备即可。3. 硬件选型与电路设计要点3.1 ESP8266 vs ESP32如何选择这是入门时最常见的困惑。简单来说可以根据以下需求做决定选择ESP8266如果你的应用场景非常简单只需要连接1-2个数字或模拟传感器如DHT11、土壤湿度传感器且对功耗极其敏感希望电池续航数月至数年同时不需要蓝牙功能。它的价格更低在深度睡眠模式下的功耗也略优于ESP32尤其是使用EXT0或EXT1唤醒时。选择ESP32如果你的项目需要连接更多传感器得益于更多的GPIO和ADC通道需要更高的处理能力双核240MHz需要蓝牙用于本地配置或信标功能或者未来可能涉及简单的边缘计算如FFT分析。ESP32的功耗虽然略高但其灵活的电源管理模块和超低功耗协处理器ULP在复杂低功耗场景下同样出色。注意对于需要5V供电的传感器如某些型号的MQ-2烟雾传感器切勿直接连接到ESP的3.3V引脚。必须使用额外的5V稳压模块如AMS1117-5.0或7805为传感器单独供电同时确保传感器的信号输出线电平是3.3V兼容的否则需要使用电平转换模块或电阻分压电路以免损坏ESP芯片。3.2 电源管理与低功耗设计精要要让一个由锂电池供电的节点工作数周甚至数月低功耗设计是灵魂。ESP在深度睡眠Deep Sleep模式下的功耗可以降到微安级别但整个系统的功耗取决于“最耗电的组件”。传感器电源控制很多传感器在空闲时也会消耗数毫安电流。理想的做法是使用一个MOSFET如SI2302或数字开关芯片如TPL5110由ESP的一个GPIO控制其电源通断。仅在采集数据的瞬间给传感器上电。ESP的深度睡眠模式定时唤醒最常用的模式。使用esp_deep_sleep(us)函数指定睡眠微秒数。唤醒后芯片会重启程序从头开始执行。需要在代码开头判断唤醒原因并快速连接Wi-Fi、上传数据。外部触发唤醒通过EXT0或EXT1引脚的电平变化唤醒。适合由外部事件如门磁开关、PIR传感器触发采集。省电核心代码逻辑// 以ESP32为例的简化流程 void setup() { Serial.begin(115200); // 1. 判断是否为深度睡眠后的启动可选 esp_sleep_wakeup_cause_t wakeup_reason esp_sleep_get_wakeup_cause(); // 2. 执行核心任务连接Wi-Fi读取传感器发送数据 performMeasurementAndUpload(); // 3. 所有任务完成后配置并进入深度睡眠 Serial.println(准备进入深度睡眠...); // 设置唤醒时间例如900秒15分钟 esp_sleep_enable_timer_wakeup(900 * 1000000ULL); // 也可以配置GPIO唤醒 // esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 0); // 低电平唤醒 // 进入深度睡眠 esp_deep_sleep_start(); } void loop() { // Deep Sleep模式下loop永远不会执行 }实时时钟RTC的必要性如果你需要数据带有精确的本地时间戳而节点又可能长时间无法连接网络获取NTP时间那么一个外置的RTC模块如DS3231精度远高于DS1307是值得投资的。它本身功耗极低~1μA可以在ESP深度睡眠时保持计时ESP唤醒后只需通过I2C读取时间即可。4. 服务器端搭建从零部署LAMP与数据接口4.1 快速搭建LAMP环境服务器是数据的中枢我们选择最经典的LAMPLinux, Apache, MySQL, PHP栈。对于初学者在Ubuntu 20.04/22.04 LTS上部署是最佳选择。# 1. 更新软件包列表 sudo apt update sudo apt upgrade -y # 2. 安装Apache sudo apt install apache2 -y # 3. 安装MySQL并运行安全配置脚本 sudo apt install mysql-server -y sudo mysql_secure_installation # 按照提示设置root密码、移除匿名用户、禁止远程root登录等 # 4. 安装PHP及MySQL扩展 sudo apt install php libapache2-mod-php php-mysql -y # 5. 重启Apache使配置生效 sudo systemctl restart apache2安装完成后在浏览器访问你的服务器IP应该能看到Apache的默认欢迎页面。PHP信息页面可以通过创建/var/www/html/info.php内容?php phpinfo(); ?来测试。4.2 创建数据库与数据表使用命令行或更友好的phpMyAdmin来操作。这里以创建一个名为sensor_cloud的数据库和一张node_01_data表为例。-- 通过MySQL命令行 CREATE DATABASE sensor_cloud CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE sensor_cloud; CREATE TABLE node_01_data ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, -- 服务器接收时间 node_time VARCHAR(20), -- 节点自带的RTC时间可选 temperature FLOAT, humidity FLOAT, battery_voltage FLOAT, rssi SMALLINT, -- 可记录信号强度用于诊断网络质量 location VARCHAR(32) -- 节点位置标识 );实操心得timestamp字段使用DATETIME类型并设置默认值为CURRENT_TIMESTAMP可以自动记录数据到达服务器的准确时间这对于校验节点时间、分析网络延迟非常有用。同时建议为timestamp字段建立索引可以大幅提升按时间范围查询图表数据的速度。4.3 编写核心PHP数据接收脚本这个脚本是连接ESP和数据库的桥梁其安全性和健壮性至关重要。以下是一个增强版的api/v1/upload.php示例?php header(Content-Type: application/json); // 1. 配置数据库连接 $servername localhost; $username sensor_user; // 强烈建议创建专用用户而非root $password YourStrongPassword123!; $dbname sensor_cloud; // 2. 获取POST原始数据JSON格式或参数 $rawData file_get_contents(php://input); $data json_decode($rawData, true); // 如果不用JSON也可以用传统的表单参数 // $api_key $_POST[api_key] ?? ; // $temperature $_POST[temp] ?? null; // 3. 安全验证第一道防线 $expected_api_key NODE_SECRET_KEY_HASHED_IN_ESP; // 应与ESP内存储的哈希值匹配 $received_api_key $data[api_key] ?? ; if (empty($received_api_key) || !hash_equals($expected_api_key, hash(sha256, $received_api_key))) { http_response_code(401); // Unauthorized echo json_encode([status error, message Invalid API key]); exit; } // 4. 验证必填数据字段 $required_fields [node_id, temp, hum, batt]; foreach ($required_fields as $field) { if (!isset($data[$field])) { http_response_code(400); // Bad Request echo json_encode([status error, message Missing field: $field]); exit; } } // 5. 连接数据库 $conn new mysqli($servername, $username, $password, $dbname); if ($conn-connect_error) { http_response_code(500); // Internal Server Error echo json_encode([status error, message DB connection failed]); exit; } // 6. 准备SQL语句使用预处理语句防止SQL注入 $table_name node_ . $conn-real_escape_string($data[node_id]) . _data; // 动态表名需要额外验证这里简单示例生产环境需严格检查表名合法性 $sql INSERT INTO $table_name (node_time, temperature, humidity, battery_voltage, rssi, location) VALUES (?, ?, ?, ?, ?, ?); $stmt $conn-prepare($sql); if ($stmt false) { echo json_encode([status error, message $conn-error]); exit; } // 7. 绑定参数并执行 $stmt-bind_param(sdddis, $data[node_time] ?? NULL, $data[temp], $data[hum], $data[batt], $data[rssi] ?? NULL, $data[loc] ?? NULL ); if ($stmt-execute()) { echo json_encode([status success, message Data inserted, insert_id $stmt-insert_id]); } else { http_response_code(500); echo json_encode([status error, message $stmt-error]); } $stmt-close(); $conn-close(); ?将此脚本放在Apache的web目录下如/var/www/html/api/v1/upload.php并确保目录权限正确sudo chown -R www-data:www-data /var/www/html。5. ESP端固件开发稳定上传与健壮性处理5.1 ESP8266数据上传核心代码解析以下是ESP8266节点固件的核心部分包含了Wi-Fi多网络切换、数据打包、HTTP上传和深度睡眠的完整流程。#include ESP8266WiFi.h #include ESP8266HTTPClient.h #include WiFiClient.h #include ArduinoJson.h // 使用v6或v7需通过库管理器安装 // 配置区 const char* ssid_list[] {Campus_WiFi_1, Lab_WiFi_2, Guest_Network}; const char* password_list[] {password1, password2, password3}; const int num_networks 3; const char* server_url http://your-server.com/api/v1/upload.php; const char* api_key_secret YourNodeSecret; // 用于生成哈希不要直接传输 const char* node_id NODE_01; const char* location Building_A_3F_Room305; const int sleep_seconds 900; // 深度睡眠时间15分钟 // // 传感器读取函数示例 (需根据实际传感器库调整) float readTemperature() { /* ... */ return 25.6; } float readHumidity() { /* ... */ return 60.2; } float readBatteryVoltage() { // 假设通过分压电阻连接到A0引脚 int adcValue analogRead(A0); float voltage (adcValue / 1024.0) * 3.3 * 2.0; // 假设分压比为1:1 return voltage; } String generateApiKeyHash(const char* secret, unsigned long epochTime) { // 简单示例使用时间戳密钥生成一个简单的哈希增加请求唯一性 // 生产环境应考虑更安全的HMAC算法 String input String(secret) String(epochTime / 300); // 每5分钟变化一次 char hash[33]; // 这里应使用一个哈希函数例如SHA256但为简化示例我们省略具体实现 // 实际可使用BearSSL或mbedTLS库的函数 sprintf(hash, %08lx, (unsigned long)input.hashCode()); // 简易替代 return String(hash); } bool connectToWiFi() { Serial.println(扫描可用的Wi-Fi网络...); int n WiFi.scanNetworks(); if (n 0) { Serial.println(未发现任何网络); return false; } for (int i 0; i n; i) { String found_ssid WiFi.SSID(i); Serial.print(发现网络: ); Serial.println(found_ssid); for (int j 0; j num_networks; j) { if (found_ssid.equals(ssid_list[j])) { Serial.print(尝试连接至: ); Serial.println(ssid_list[j]); WiFi.begin(ssid_list[j], password_list[j]); int retries 0; while (WiFi.status() ! WL_CONNECTED retries 20) { delay(500); Serial.print(.); retries; } if (WiFi.status() WL_CONNECTED) { Serial.println(\nWi-Fi连接成功!); Serial.print(IP地址: ); Serial.println(WiFi.localIP()); return true; } else { Serial.println(\n连接失败尝试下一个已知网络...); WiFi.disconnect(); delay(100); } } } } Serial.println(无法连接到任何已知网络); return false; } void uploadData() { if (WiFi.status() ! WL_CONNECTED) { Serial.println(Wi-Fi未连接无法上传); return; } WiFiClient client; HTTPClient http; // 准备JSON数据 DynamicJsonDocument doc(512); doc[node_id] node_id; doc[temp] readTemperature(); doc[hum] readHumidity(); doc[batt] readBatteryVoltage(); doc[rssi] WiFi.RSSI(); doc[loc] location; // 生成带时间因子的API Key哈希简易版 unsigned long epochTime 0; // 此处应从NTP或RTC获取真实时间 // 如果无法获取网络时间可以使用开机后的毫秒数作为粗略替代 epochTime millis() / 1000; doc[api_key] generateApiKeyHash(api_key_secret, epochTime); String jsonString; serializeJson(doc, jsonString); Serial.println(准备发送的JSON: jsonString); // 开始HTTP请求 http.begin(client, server_url); http.addHeader(Content-Type, application/json); int httpResponseCode http.POST(jsonString); if (httpResponseCode 0) { String response http.getString(); Serial.print(HTTP响应代码: ); Serial.println(httpResponseCode); Serial.print(服务器响应: ); Serial.println(response); // 可解析响应进行更细致的处理 DynamicJsonDocument resDoc(256); DeserializationError error deserializeJson(resDoc, response); if (!error resDoc[status] success) { Serial.println(数据上传成功); } else { Serial.println(服务器处理数据可能失败); } } else { Serial.print(POST请求失败错误: ); Serial.println(http.errorToString(httpResponseCode).c_str()); } http.end(); } void setup() { Serial.begin(115200); delay(100); // 等待串口稳定 // 打印唤醒原因仅ESP32有丰富的原因ESP8266较简单 Serial.println(\n ESP8266 传感节点启动 ); // 连接Wi-Fi if (!connectToWiFi()) { Serial.println(Wi-Fi连接失败将直接进入睡眠); ESP.deepSleep(sleep_seconds * 1000000); return; // 不会执行到这里 } // 读取传感器并上传数据 uploadData(); // 短暂延迟确保数据发送完成 delay(1000); // 断开Wi-Fi连接进入深度睡眠 WiFi.disconnect(true); delay(100); Serial.println(进入深度睡眠...); ESP.deepSleep(sleep_seconds * 1000000); } void loop() { // 深度睡眠模式下不会执行到这里 }5.2 ESP32的额外优势与代码调整ESP32的代码逻辑与ESP8266类似但库的引用略有不同使用WiFi.h和HTTPClient.h。此外ESP32提供了更精细的功耗控制和外设管理。更灵活的深度睡眠ESP32除了定时唤醒还支持触摸唤醒、外部中断唤醒等。RTC集成可以使用内置的RTC存储器在深度睡眠期间保存少量数据如连接重试次数。双核处理虽然在这个简单应用中优势不明显但你可以将Wi-Fi连接和数据上传任务放在一个核心传感器读取放在另一个核心理论上可以缩短唤醒工作时间。代码调整示例// 替换ESP8266的库 #include WiFi.h #include HTTPClient.h // 深度睡眠函数不同 #include esp_sleep.h // 进入深度睡眠 esp_sleep_enable_timer_wakeup(sleep_seconds * 1000000ULL); esp_deep_sleep_start();6. 数据可视化使用ChartDirector打造专业仪表盘数据存入数据库后可视化是呈现价值的关键。ChartDirector是一款功能强大且易于集成的商业图表库其PHP版本非常适合本项目。6.1 安装与配置ChartDirector下载访问ChartDirector官网下载适用于Linux的PHP版本。安装通常只需解压到服务器目录例如/usr/lib/ChartDirector。配置PHP在php.ini文件中添加扩展路径。# 编辑php.ini sudo nano /etc/php/7.4/apache2/php.ini # 在文件末尾添加路径根据实际调整 extension/usr/lib/ChartDirector/lib/phpchartdir.so重启Apachesudo systemctl restart apache2。6.2 创建动态数据图表PHP页面以下是一个charts/live_temperature.php的示例它从数据库读取最新24小时的数据并生成温度曲线图。?php require_once(/usr/lib/ChartDirector/lib/phpchartdir.php); // 数据库连接 $db new mysqli(localhost, sensor_user, YourStrongPassword123!, sensor_cloud); if ($db-connect_error) { die(连接失败: . $db-connect_error); } // 查询最近24小时的数据 $query SELECT timestamp, temperature, humidity FROM node_01_data WHERE timestamp DATE_SUB(NOW(), INTERVAL 24 HOUR) ORDER BY timestamp ASC ; $result $db-query($query); $timestamps array(); $temperatures array(); $humidities array(); while ($row $result-fetch_assoc()) { // 将时间戳转换为ChartDirector可用的格式自0001-01-01以来的秒数 $phpTime strtotime($row[timestamp]); $chartTime chartTime2($phpTime); $timestamps[] $chartTime; $temperatures[] $row[temperature]; $humidities[] $row[humidity]; } $db-close(); // 创建图表对象大小800x400 $c new XYChart(800, 400); // 设置图表标题 $c-addTitle(节点 NODE_01 - 温湿度趋势 (最近24小时), 仿宋_GB2312.ttf, 16); // 设置X轴为时间轴 $c-xAxis-setDateScale(min($timestamps), max($timestamps)); $c-xAxis-setLabelFormat({value|hh:nn}); $c-xAxis-setTitle(时间, 仿宋_GB2312.ttf, 12); // 设置左侧Y轴为温度轴 $c-yAxis-setTitle(温度 (°C), 仿宋_GB2312.ttf, 12); $c-yAxis-setLinearScale(10, 40); // 根据实际数据范围调整 // 添加温度曲线层 $temperatureLayer $c-addLineLayer($temperatures, 0xff0000, 温度); $temperatureLayer-setLineWidth(2); $temperatureLayer-setDataLabelFormat({value|1}°C); // 添加右侧Y轴为湿度轴 $rightYAxis $c-addAxis(Right, 0); $rightYAxis-setTitle(湿度 (%RH), 仿宋_GB2312.ttf, 12); $rightYAxis-setLinearScale(0, 100); // 添加湿度曲线层关联到右侧Y轴 $humidityLayer $c-addLineLayer($humidities, 0x0000ff, 湿度, $rightYAxis); $humidityLayer-setLineWidth(2); $humidityLayer-setDataLabelFormat({value|1}%); // 设置图例框 $c-addLegend(650, 30, true, 仿宋_GB2312.ttf, 10)-setBackground(Transparent); // 设置自动刷新每5分钟刷新一次页面 header(Content-type: image/png); header(Refresh:300); // 关键实现图表自动更新 echo $c-makeChart2(PNG); ?将上述文件放在web目录通过浏览器访问即可看到自动刷新的图表。你可以创建多个这样的页面监控不同节点或不同指标。7. 部署、调试与运维实战经验7.1 节点部署的实用技巧Wi-Fi信号勘测在部署前使用手机APP或ESP本身的WiFi.scanNetworks()功能在目标位置测试各个可用Wi-Fi的信号强度RSSI。选择信号稳定通常RSSI -70dBm的网络进行配置。电源估算这是保证续航的关键。计算平均功耗总功耗 (唤醒工作时间 * 工作电流 睡眠时间 * 睡眠电流) / 总周期。例如ESP8266工作电流约70mA睡眠电流20μA每15分钟工作10秒。则平均电流 ≈(10*0.07 890*0.00002) / 900 ≈ 0.0008A 0.8mA。一块2000mAh的锂电池理论续航约为2000mAh / 0.8mA ≈ 2500小时 ≈ 104天。实际需考虑电池自放电、传感器功耗等打7-8折。防水与防护室外部署必须考虑防水。使用IP67防护盒传感器探头引出线处用防水胶密封。天线尽量外置或朝向信号源方向。7.2 常见故障排查指南下表列出了部署和运行中可能遇到的典型问题及解决方法问题现象可能原因排查步骤与解决方案数据偶尔或持续不上传1. Wi-Fi连接不稳定或断开。2. 服务器PHP脚本错误或超时。3. ESP供电不足导致重启。1. 在ESP代码中增加WiFi.RSSI()记录并上传分析信号质量。增加连接重试机制和备用网络列表。2. 查看服务器Apache错误日志(/var/log/apache2/error.log)检查PHP脚本语法和数据库权限。在PHP脚本开头添加error_log(print_r($_POST, true));记录接收到的数据。3. 使用万用表测量ESP唤醒瞬间的电压是否被拉低。建议电源电容并联1000μF以上电解电容。数据库中出现重复或异常数据1. ESP因上传失败重复发送。2. 服务器时间不同步导致时间戳错乱。3. 传感器读数异常。1. 实现ESP端的“至少一次”送达机制只有收到服务器成功的HTTP响应如status: success后才进入睡眠。可在代码中解析HTTP响应体判断。2. 确保服务器NTP服务正常运行 (sudo timedatectl status)。在ESP端如果可能尽量使用从服务器返回的时间或NTP校准本地RTC。3. 在PHP脚本中加入数据合理性校验如温度范围(-40, 80)超出范围则记录日志并丢弃。节点续航远低于预期1. 深度睡眠未成功进入。2. 传感器或外围电路在睡眠时仍在耗电。3. 电池容量衰减或环境温度过低。1. 在ESP.deepSleep()或esp_deep_sleep_start()前添加串口打印确认执行到该语句。测量睡眠时ESP的VCC电流应在微安级。2. 使用万用表电流档串联测量整个系统的睡眠电流。逐一断开传感器电源定位漏电元件。务必用GPIO控制传感器电源开关。3. 使用质量好的锂亚硫酰氯电池ER系列用于低温环境其自放电极低。ChartDirector图表不显示或报错1. PHP扩展未正确加载。2. 缺少中文字体文件。3. 数据库查询结果为空。1. 创建phpinfo()页面检查是否有phpchartdir模块。检查php.ini扩展路径是否正确。2. 将字体文件如.ttf上传到服务器并在图表代码中指定正确路径。3. 在图表PHP脚本中先var_dump($timestamps)等数组确保有数据被查询出来。检查SQL查询条件和时间范围。7.3 系统优化与进阶思路数据缓冲与断点续传在ESP的SPIFFS或EEPROM中开辟一小块区域作为数据缓冲区。当上传失败时将数据暂存。下次唤醒时优先发送历史积压数据。注意防止缓冲区溢出。OTA远程升级为每个节点实现OTA功能当需要更新固件时只需在服务器放置新固件文件节点在唤醒检查时发现更新并自动下载刷写极大简化后期维护。使用MQTT替代HTTP对于节点数量极大100或数据上报频率高的场景可以考虑使用MQTT协议。MQTT是轻量级的发布/订阅模型比HTTP更节省带宽和连接开销。服务器端部署Mosquitto MQTT Broker并编写一个MQTT订阅者将消息写入数据库。数据聚合与告警在服务器端可以编写定时任务Cron Job定期检查数据库数据。例如计算过去10分钟的平均温度如果超过阈值则触发发送邮件、短信或通过Telegram Bot发送告警信息。这个由ESP构建的分布式云系统其魅力在于极高的自由度和极低的试错成本。你可以从监控阳台花盆的土壤湿度开始逐步扩展到管理整个小型温室、仓库、甚至楼宇的传感网络。每一次调试和解决问题的过程都会让你对物联网系统的底层细节有更深刻的理解。当看到自己部署的节点稳定运行数月数据如涓涓细流汇入你自己的数据库并形成图表时那种成就感和掌控感是使用任何现成云平台都无法比拟的。