news 2026/5/25 22:41:16

基于ESP8266与MQTT的家庭水压自动控制系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于ESP8266与MQTT的家庭水压自动控制系统设计与实现

1. 项目概述与核心需求解析

家里水压不稳、供水时断时续,这大概是很多朋友都遇到过的烦心事。我所在的城市供水情况就很不理想,为了解决这个问题,我不得不自己动手,搭建了一套基于ESP8266微控制器的家庭水压增压与储水自动控制系统。这套系统的核心,就是利用一个“hidroneumatic”(气动压力罐,国内常称为压力罐或无塔供水器)来稳定家庭用水压力,同时通过额外的水泵和阀门,实现储水罐的自动补水,确保家里24小时都有足够压力的水可用。

整个项目听起来复杂,但拆解开来,核心需求非常明确:自动化远程监控。我需要系统能自动判断何时该启动增压泵给家里供水,何时该给楼顶的储水罐补水,并且在储水罐快空的时候能及时报警,防止水泵干烧。同时,作为一个喜欢折腾的开发者,我当然不希望每次操作都要跑到设备间去按开关,一个能通过手机或电脑远程查看状态、进行控制的Web界面是必不可少的。最终,我选择了ESP8266作为控制大脑,搭配MQTT协议进行设备间通信,并开发了一个简单的HTML Web App作为控制面板,还接入了Cayenne平台作为备用监控手段。下面,我就把这套系统的设计思路、实现细节以及踩过的坑,毫无保留地分享给大家。

2. 系统整体设计与核心组件选型

2.1 为什么是ESP8266 + MQTT + Web App的组合?

在开始动手之前,方案选型是关键。我之所以选择这个技术栈,是基于以下几个核心考量:

首先,ESP8266几乎是智能家居DIY项目的“标配”。它价格低廉(一片NodeMCU开发板不到20元),集成了Wi-Fi功能,GPIO引脚足够驱动继电器、读取传感器,并且有庞大的Arduino社区支持,开发门槛极低。对于控制几个水泵、阀门和传感器来说,它的性能绰绰有余。

其次,MQTT协议是物联网设备通信的“轻量级高速公路”。它的发布/订阅模式非常适合我这个场景:ESP8266作为客户端,将传感器数据(如水位状态、泵的运行状态)发布到特定的主题(Topic);同时,它订阅控制主题,等待来自Web App或手机端的指令(如“开启增压泵”)。这种解耦的设计使得增加新的控制终端(比如未来加个语音助手)变得非常容易,只需要让新终端订阅和发布到正确的主题即可。我选择了Mosquitto作为本地的MQTT代理服务器(Broker),运行在一台常年开机的树莓派上,稳定又可靠。

最后,HTML Web App提供了最灵活、最通用的控制界面。它不依赖任何特定的手机操作系统,只需要一个浏览器就能访问。我用简单的HTML、CSS和JavaScript搭建了一个控制面板,通过WebSocket或HTTP长轮询与一个后端服务通信,而这个后端服务再与MQTT Broker交互,从而实现了网页与ESP8266的双向通信。为了多一层保障,我还接入了Cayenne这个第三方IoT平台,它提供了现成的仪表盘和手机App,可以让我在外出时快速查看系统状态,作为Web App的补充。

2.2 核心硬件组件清单与功能解析

我的系统硬件主要由执行机构、传感器和控制显示单元三部分组成:

  1. 执行机构

    • 增压泵(Hidroneumatic Pump):这是系统的“心脏”,负责从压力罐向家庭管网供水,维持水压。我选用了一台标准的家用自吸增压泵。
    • 补水小泵(Water Pump):当市政供水压力太低,无法靠重力流入储水罐时,由这台小功率水泵负责将水抽到楼顶的储水罐中。
    • 电磁阀(Solenoid Valves,共3个)
      • 阀1:安装在市政供水管入口,当水压足够时自动打开,向储水罐注水。
      • 阀2 & 阀3:用于控制水流路径,例如隔离增压泵系统进行维护等。在我的配置中,其中一个用于在储水罐空时,切断增压泵的进水,防止干烧。
  2. 传感器

    • 高水位传感器(Full Sensor):安装在储水罐内部顶端。当水位达到这里,表示水罐已满,需要停止补水(无论是来自市政管道还是小泵)。我选用的是耐腐蚀的浮球式液位开关,简单可靠。
    • 低水位传感器(Empty Sensor):安装在储水罐底部靠上的位置。当水位低于此传感器,说明储水罐即将见底,系统会触发声光报警(蜂鸣器),并强制停止增压泵,保护设备。
    • 运动传感器:安装在泵房内,用于人体感应。检测到有人进入时自动点亮照明灯,15秒后自动关闭,方便夜间检修。
  3. 控制与显示单元

    • ESP8266开发板(NodeMCU):主控制器。
    • 继电器模块:用于控制220V的增压泵、补水泵以及电磁阀的通断。特别注意:驱动电磁阀需要留意是常开型还是常闭型,以及电压是12V、24V还是220V交流,这决定了你需要选择什么样的继电器和电源。
    • 蜂鸣器:用于低水位报警。
    • LED灯带/灯泡:泵房照明,由继电器控制。
    • LCD显示屏(可选):我使用了一块I2C接口的1602液晶屏,直接连接ESP8266,用于本地显示系统状态,如“水罐:满”、“增压泵:运行中”、“网络:已连接”等,在调试和本地查看时非常直观。

重要提示:安全第一!整个系统涉及220V强电控制,接线时必须确保断电操作。建议将ESP8266、继电器模块等弱电部分封装在一个绝缘良好的控制箱内,强电部分(泵、阀的电源线)通过接线端子与继电器输出端连接,两者之间做好物理隔离。如果不熟悉强电操作,请务必寻求专业电工的帮助。

3. 电路连接与控制器编程详解

3.1 ESP8266引脚分配与接线图

合理的引脚规划是稳定运行的基础。下面是我的接线方案,你可以根据手头的模块进行调整:

组件类型连接至ESP8266引脚说明
高水位传感器数字输入 (INPUT_PULLUP)D5 (GPIO14)常开型,水位满时闭合,引脚读到LOW
低水位传感器数字输入 (INPUT_PULLUP)D6 (GPIO12)常开型,水位空时闭合,引脚读到LOW
运动传感器数字输入D7 (GPIO13)输出高电平触发
增压泵继电器数字输出D1 (GPIO5)HIGH触发继电器吸合,泵启动
补水小泵继电器数字输出D2 (GPIO4)HIGH触发继电器吸合,泵启动
电磁阀1继电器数字输出D3 (GPIO0)注意:GPIO0有特殊用途,上电时需为高才能进入正常模式。确保电路稳定。
电磁阀2继电器数字输出D4 (GPIO2)内部上拉,接LED时注意。
蜂鸣器数字输出D8 (GPIO15)低电平触发蜂鸣器
照明灯继电器数字输出RX (GPIO3)用作普通GPIO时,需注意串口下载的影响
I2C LCD显示屏I2CD1 (SCL), D2 (SDA)与D1、D2引脚复用,需使用Wire库

接线心得

  • 上拉电阻:对于浮球开关这类机械传感器,我强烈建议在代码中使用INPUT_PULLUP模式启用ESP8266的内部上拉电阻。这样,传感器断开时引脚被拉高到3.3V(读到HIGH),闭合时直接接地(读到LOW),省去了外接电阻的麻烦,电路更简洁。
  • GPIO0和GPIO2:这两个引脚在ESP8266启动时有特殊状态要求。GPIO0在上电时决定启动模式(高电平=正常运行,低电平=进入下载模式)。因此,连接在GPIO0上的设备(如我的电磁阀1继电器)必须确保在ESP8266上电瞬间处于“断开”或“高电平”状态,否则可能导致启动失败。在设计电路时,要避免这些引脚在上电瞬间被意外拉低。
  • 电源:ESP8266和继电器模块需要稳定的5V或3.3V电源。继电器控制线圈电压可能是5V,注意电平匹配。如果ESP8266的3.3V GPIO驱动5V继电器模块信号端,通常问题不大(很多5V继电器模块在3.3V下也能触发),但最稳妥的方式是确认模块支持3.3V触发,或使用电平转换模块。

3.2 核心控制逻辑与Arduino代码框架

系统的“大脑”是运行在ESP8266上的Arduino程序。其核心是一个状态机,根据传感器输入和MQTT指令来决定输出动作。以下是主循环逻辑的简化框架和关键代码片段:

#include <ESP8266WiFi.h> #include <PubSubClient.h> // MQTT客户端库 #include <Wire.h> #include <LiquidCrystal_I2C.h> // I2C LCD库 // 网络和MQTT配置 const char* ssid = "Your_WiFi_SSID"; const char* password = "Your_WiFi_Password"; const char* mqtt_server = "192.168.1.100"; // 你的MQTT Broker地址 WiFiClient espClient; PubSubClient client(espClient); LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C地址通常是0x27或0x3F // 引脚定义 #define PIN_FULL_SENSOR 14 // D5 #define PIN_EMPTY_SENSOR 12 // D6 #define PIN_PIR_SENSOR 13 // D7 #define PIN_BOOSTER_PUMP 5 // D1 #define PIN_FILL_PUMP 4 // D2 #define PIN_VALVE1 0 // D3 #define PIN_BUZZER 15 // D8 #define PIN_LIGHT 3 // RX // 状态变量 bool tankFull = false; bool tankEmpty = false; bool motionDetected = false; unsigned long lightOffTime = 0; const unsigned long LIGHT_TIMEOUT = 15000; // 15秒 void setup() { Serial.begin(115200); pinMode(PIN_FULL_SENSOR, INPUT_PULLUP); pinMode(PIN_EMPTY_SENSOR, INPUT_PULLUP); pinMode(PIN_PIR_SENSOR, INPUT); pinMode(PIN_BOOSTER_PUMP, OUTPUT); digitalWrite(PIN_BOOSTER_PUMP, LOW); // 初始关闭 // ... 初始化其他输出引脚 lcd.init(); lcd.backlight(); lcd.print("System Booting..."); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(mqttCallback); // 设置收到MQTT消息时的回调函数 } void loop() { if (!client.connected()) { reconnectMQTT(); } client.loop(); // 维持MQTT连接并处理消息 // 1. 读取传感器状态 tankFull = (digitalRead(PIN_FULL_SENSOR) == LOW); // 传感器闭合为LOW tankEmpty = (digitalRead(PIN_EMPTY_SENSOR) == LOW); motionDetected = (digitalRead(PIN_PIR_SENSOR) == HIGH); // 2. 核心控制逻辑 // 空罐报警与保护 if (tankEmpty) { digitalWrite(PIN_BUZZER, LOW); // 触发蜂鸣器(低电平有效) // 强制停止所有泵和进水阀,防止干烧 digitalWrite(PIN_BOOSTER_PUMP, LOW); digitalWrite(PIN_FILL_PUMP, LOW); digitalWrite(PIN_VALVE1, LOW); // 关闭进水阀 lcd.setCursor(0, 1); lcd.print("ALARM: Tank EMPTY!"); // 通过MQTT发布报警状态 client.publish("home/water/tank/status", "EMPTY_ALARM"); } else { digitalWrite(PIN_BUZZER, HIGH); // 关闭蜂鸣器 // 正常逻辑:根据水位和指令控制 controlBoosterPump(); // 增压泵控制函数 controlWaterFilling(); // 补水控制函数 } // 3. 照明自动控制 if (motionDetected) { digitalWrite(PIN_LIGHT, HIGH); // 开灯 lightOffTime = millis() + LIGHT_TIMEOUT; client.publish("home/water/light/status", "ON"); } if (millis() > lightOffTime) { digitalWrite(PIN_LIGHT, LOW); // 关灯 // 注意:这里可以加一个状态判断,避免频繁发布MQTT消息 } // 4. 更新LCD本地显示 updateLCDDisplay(); delay(100); // 短暂延时,防止循环过快 } // MQTT消息回调函数 void mqttCallback(char* topic, byte* payload, unsigned int length) { String message; for (int i = 0; i < length; i++) { message += (char)payload[i]; } Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); Serial.println(message); if (String(topic) == "home/water/booster_pump/set") { if (message == "ON" && !tankEmpty) { // 空罐时拒绝手动开启 digitalWrite(PIN_BOOSTER_PUMP, HIGH); client.publish("home/water/booster_pump/status", "ON"); } else if (message == "OFF") { digitalWrite(PIN_BOOSTER_PUMP, LOW); client.publish("home/water/booster_pump/status", "OFF"); } } // ... 处理其他主题的控制指令,如 fill_pump/set, valve1/set, light/set 等 }

代码关键点解析

  • 状态优先tankEmpty(空罐)是最高优先级的条件。一旦触发,无论手动指令如何,系统都会强制停止所有水泵并报警。这是最重要的安全逻辑。
  • MQTT主题设计:我采用了典型的“set/status”模式。例如,向home/water/booster_pump/set主题发送ON/OFF可以控制增压泵,而ESP8266会向home/water/booster_pump/status主题发布当前状态。这种设计清晰且易于扩展。
  • 防抖与状态发布:对于运动传感器和开关指令,需要考虑防抖。同时,避免在loop()中频繁发布不变的MQTT状态,可以在状态真正改变时才发布,以减少网络流量和Broker压力。

4. MQTT Broker搭建与Web App开发

4.1 搭建本地Mosquitto MQTT Broker

要让ESP8266和Web App通信,你需要一个MQTT代理服务器。在本地局域网部署Mosquitto是最简单稳定的方案。

  1. 在树莓派或旧电脑上安装(以Debian/Ubuntu为例):

    sudo apt update sudo apt install mosquitto mosquitto-clients sudo systemctl enable mosquitto sudo systemctl start mosquitto

    安装后,Mosquitto服务会自动启动,监听1883端口(MQTT默认端口)和8883端口(SSL)。

  2. 基本安全配置(可选但推荐): 编辑配置文件/etc/mosquitto/mosquitto.conf,可以设置用户名密码。

    allow_anonymous false # 禁止匿名连接 password_file /etc/mosquitto/passwd

    然后创建密码文件:

    sudo mosquitto_passwd -c /etc/mosquitto/passwd your_username

    系统会提示你输入密码。之后重启Mosquitto服务:sudo systemctl restart mosquitto

  3. 测试: 在服务器上打开两个终端窗口。 窗口1订阅测试主题:

    mosquitto_sub -h localhost -t "test/topic" -u "your_username" -P "your_password"

    窗口2发布消息:

    mosquitto_pub -h localhost -t "test/topic" -m "Hello MQTT" -u "your_username" -P "your_password"

    如果窗口1能收到“Hello MQTT”,说明Broker运行正常。

实操心得:对于家庭使用,如果设备都在同一局域网,初期可以先用allow_anonymous true(允许匿名)快速测试。等所有功能调通后,再启用密码认证。记得在ESP8266和Web App的后端代码中配置相同的用户名和密码。

4.2 开发简易HTML Web控制面板

Web App的目标是提供一个直观的界面。前端用HTML/CSS/JS,后端我用的是Python的Flask框架,因为它轻量且与MQTT集成方便。当然,你也可以用Node.js、PHP等。

前端页面 (index.html) 核心部分

<div class="container"> <h2>家庭水系统控制面板</h2> <div class="status-card"> <h3>储水罐状态</h3> <p>水位: <span id="tankStatus">读取中...</span></p> <p>报警: <span id="alarmStatus">无</span></p> </div> <div class="control-card"> <h3>增压泵控制</h3> <p>状态: <span id="boosterPumpStatus">-</span></p> <button onclick="sendCommand('booster_pump', 'ON')" class="btn btn-on">开启</button> <button onclick="sendCommand('booster_pump', 'OFF')" class="btn btn-off">关闭</button> </div> <!-- 其他控制卡:补水泵、电磁阀1、照明等 --> </div> <script> // 使用WebSocket或Ajax与后端通信 function sendCommand(device, action) { fetch(`/control/${device}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({action: action}) }) .then(response => response.json()) .then(data => console.log(data)); } // 使用Server-Sent Events (SSE) 或WebSocket实时更新状态 // 这里以轮询为例(简化) function updateStatus() { fetch('/status') .then(response => response.json()) .then(data => { document.getElementById('tankStatus').textContent = data.tank; document.getElementById('boosterPumpStatus').textContent = data.booster_pump; // ... 更新其他状态 }); } setInterval(updateStatus, 2000); // 每2秒更新一次状态 </script>

后端Flask应用 (app.py) 核心逻辑

from flask import Flask, render_template, jsonify, request import paho.mqtt.client as mqtt import threading app = Flask(__name__) # MQTT配置 MQTT_BROKER = "localhost" MQTT_PORT = 1883 MQTT_USER = "your_username" MQTT_PASS = "your_password" # 全局状态存储 current_status = { "tank": "未知", "booster_pump": "离线", "alarm": "无" } def on_mqtt_connect(client, userdata, flags, rc): print("Connected to MQTT Broker") # 订阅所有状态主题 client.subscribe("home/water/+/status") def on_mqtt_message(client, userdata, msg): topic = msg.topic payload = msg.payload.decode() # 解析主题并更新状态 if "tank/status" in topic: current_status["tank"] = payload elif "booster_pump/status" in topic: current_status["booster_pump"] = payload elif "alarm" in topic: current_status["alarm"] = payload # ... 处理其他主题 # 启动MQTT客户端线程 mqtt_client = mqtt.Client() mqtt_client.username_pw_set(MQTT_USER, MQTT_PASS) mqtt_client.on_connect = on_mqtt_connect mqtt_client.on_message = on_mqtt_message mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60) mqtt_thread = threading.Thread(target=mqtt_client.loop_forever) mqtt_thread.daemon = True mqtt_thread.start() @app.route("/") def index(): return render_template("index.html") @app.route("/status") def get_status(): return jsonify(current_status) @app.route("/control/<device>", methods=["POST"]) def control_device(device): action = request.json.get("action") topic = f"home/water/{device}/set" mqtt_client.publish(topic, action) return jsonify({"success": True, "message": f"Sent {action} to {device}"}) if __name__ == "__main__": app.run(host='0.0.0.0', port=5000, debug=True)

部署要点:你可以将这个Flask应用部署在和Mosquitto同一台树莓派上。使用gunicornuWSGI作为生产环境WSGI服务器,并用nginx做反向代理,这样就能通过http://你的树莓派IP来访问控制面板了。

5. 系统集成、调试与故障排查实录

5.1 分阶段集成与调试策略

不要试图一次性接好所有硬件并写完所有代码。分阶段调试是成功的关键。

  1. 第一阶段:ESP8266基础测试

    • 目标:让ESP8266连接Wi-Fi,并能通过串口打印信息。
    • 步骤:烧录一个最简单的Blink程序,然后写一个连接Wi-Fi并打印IP地址的程序。确保网络连通性。
  2. 第二阶段:MQTT通信测试

    • 目标:ESP8266能连接上Mosquitto Broker,并订阅/发布消息。
    • 步骤:编写一个测试程序,让ESP8266向某个主题(如test/esp8266)每秒发布一个“hello”消息,同时订阅该主题。在电脑上用mosquitto_sub观察是否收到,并用mosquitto_pub发送消息看ESP8266串口是否打印出来。
  3. 第三阶段:单个执行器控制测试

    • 目标:通过MQTT指令控制一个继电器(比如接一盏台灯)。
    • 步骤:接好一个继电器和负载。修改代码,让ESP8266订阅home/water/light/set主题,收到ON/OFF后控制对应GPIO高低电平。通过Web App或MQTT客户端工具发送指令测试。
  4. 第四阶段:传感器读取测试

    • 目标:正确读取水位传感器、运动传感器的状态,并通过MQTT发布。
    • 步骤:接好传感器,在loop()中读取其状态并通过串口打印。确认逻辑正确(如满水传感器触发时是否为LOW)。然后添加MQTT发布代码,将状态发送到像home/water/sensor/full这样的主题。
  5. 第五阶段:核心逻辑实现

    • 目标:将传感器状态与控制逻辑结合起来。
    • 步骤:实现controlBoosterPump()controlWaterFilling()函数。例如,增压泵的自动逻辑可能是:当压力罐压力低于某个阈值(如果有压力传感器)或用水点打开时启动,压力达到上限时停止。补水逻辑:当储水罐未满且市政水压足够(或定时)时,打开电磁阀1;如果水压不足,则启动补水小泵。
  6. 第六阶段:Web App集成

    • 目标:前端页面能显示状态并发送控制指令。
    • 步骤:先让Flask后端能通过MQTT发布控制指令。测试通过后,再实现前端状态更新(先用简单的轮询,稳定后可考虑升级为WebSocket实现真正实时)。

5.2 常见问题与排查技巧

在搭建过程中,我遇到了不少问题,这里总结一下:

问题现象可能原因排查步骤与解决方案
ESP8266无法连接Wi-FiSSID/密码错误;路由器设置(如MAC过滤);信号太弱。1. 检查代码中SSID/密码。2. 用手机确认Wi-Fi可连。3. 将ESP8266靠近路由器测试。4. 查看串口打印的具体错误代码。
ESP8266无法连接MQTT BrokerBroker地址/端口错误;网络防火墙阻止;Broker未运行或需认证。1.ping一下Broker的IP地址。2. 在ESP8266上尝试telnet <broker_ip> 1883看端口通不通。3. 检查Broker服务状态sudo systemctl status mosquitto。4. 确认代码中的用户名密码是否正确。
继电器有响声但不动作/负载不工作继电器驱动电压不足;负载功率超过继电器额定值;接线错误。1. 用万用表测量继电器线圈两端电压是否达到额定值(如5V)。2. 确认负载(水泵、电磁阀)的功率(瓦数)在继电器触点容量(如10A 250VAC)以内。3. 检查强电线路是否接通。
水位传感器状态不稳定(跳动)机械抖动;接触不良;信号干扰。1.软件防抖:在代码中,连续多次读取(如50ms内)状态一致才认为有效。2. 检查传感器接线是否牢固。3. 尝试为传感器信号线并联一个0.1uF的电容到地,滤除高频干扰。
Web页面状态更新延迟大使用了HTTP轮询且间隔太长;后端或网络延迟。1. 缩短轮询间隔(如从5秒改为2秒),但要权衡服务器压力。2.升级方案:将前端与后端的通信改为WebSocket,实现服务器主动推送,这是最实时的方法。Flask可以使用Flask-SocketIO库。
系统偶尔重启或死机电源功率不足;代码中有内存泄漏或看门狗超时。1.电源是关键!水泵、电磁阀启动瞬间电流很大,可能导致ESP8266电压被拉低而重启。务必为ESP8266和继电器模块提供独立、充足的电源(如5V 2A以上的适配器),并与水泵的大功率电源分开。2. 检查代码中是否有阻塞操作(如长delay()),考虑使用非阻塞定时(millis())。3. 启用ESP8266的看门狗,并在loop()中定期喂狗。
MQTT消息丢失网络不稳定;QoS等级为0;客户端ID冲突。1. 使用MQTT的QoS 1或2等级(确保消息送达,但会增加开销)。client.publish(topic, payload, 1)。2. 确保每个ESP8266有唯一的客户端ID。3. 在loop()中确保client.loop()被频繁调用。

一个关键的避坑经验:电磁阀的选型和控制。我最初买的是“常闭型”电磁阀,即断电时阀门关闭,通电时打开。这符合我的需求(正常关闭,需要注水时通电打开)。但还有“常开型”,逻辑相反。接线时一定要分清。另外,电磁阀通常是感性负载,断开时会产生反向电动势,可能会损坏ESP8266的GPIO。务必在继电器控制电磁阀线圈的两端,并联一个“续流二极管”(如1N4007),阴极接电源正极,阳极接负极,以吸收反向电压。

6. 功能扩展与优化思路

当基础系统稳定运行后,可以考虑一些增强功能,让系统更智能、更可靠:

  1. 增加压力传感器:在压力罐的输出管路上安装一个模拟量压力传感器(如MPX5700AP),连接到ESP8266的ADC引脚。这样,你可以实现更精准的增压泵控制:当压力低于设定下限时自动启动,达到上限时停止,而不是依赖简单的开关信号。你可以在Web App上实时显示水压曲线图。

  2. 实现定时与智能补水:目前的补水逻辑可能比较简单(没满就补)。可以增加定时功能,例如只在夜间水压高、用水低峰期开启市政补水阀。或者根据用水习惯(通过流量计估算)预测水箱水量,智能安排补水时间。

  3. 接入语音助手或主流平台:通过开源项目如Home Assistant,可以将你的MQTT设备轻松集成进去。这样,你就能用天猫精灵、小爱同学或Google Assistant通过Home Assistant来语音控制水泵和查看状态了,实现了更高级的智能家居联动。

  4. 数据记录与可视化:让Flask后端将接收到的所有MQTT状态消息(水位、泵状态、压力值)存入数据库(如SQLite或InfluxDB)。然后利用Grafana或简单的Chart.js图表,在Web App上展示历史水位变化、水泵每日运行时长、耗电估算等,这对于了解家庭用水模式和设备维护很有帮助。

  5. 增加冗余与报警升级:除了本地蜂鸣器,可以增加更远程的报警。例如,当低水位报警触发时,除了本地响铃,系统可以通过Telegram Bot、Bark或企业微信机器人向你的手机发送紧急通知。这需要ESP8266或后端服务能够访问外网API。

这个项目从构思到稳定运行,前后断断续续花了我一个多月的时间,大部分时间都在调试硬件连接、解决电源干扰和优化控制逻辑上。最大的成就感莫过于深夜在手机上点一下,听到楼下泵房传来水泵启动的声音,或者出差在外突然收到“水箱已满”的通知时的安心。自己动手搭建的系统,不仅解决了实际的生活痛点,更是一个不断学习、调试和优化的过程,其中的乐趣远非购买一个成品所能比拟。希望我的这份详细记录,能为你提供一份切实可行的参考蓝图。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 22:40:04

告别浏览器缓存 GET 请求:除了改用 POST,还有这 6 种方法

告别浏览器缓存 GET 请求&#xff1a;除了改用 POST&#xff0c;还有这 6 种方法 文章目录告别浏览器缓存 GET 请求&#xff1a;除了改用 POST&#xff0c;还有这 6 种方法方法一&#xff1a;设置 HTTP 响应头&#xff08;后端标准方案&#xff09;后端代码示例&#xff08;Nod…

作者头像 李华
网站建设 2026/5/25 22:37:29

Verilog代码生成:跨语言转换提升LLM硬件设计能力

1. 项目概述在数字电路设计领域&#xff0c;硬件描述语言(HDL)扮演着至关重要的角色。作为RTL(寄存器传输级)设计的标准语言&#xff0c;Verilog被广泛应用于FPGA编译器、逻辑综合工具等硬件设计自动化流程中。然而&#xff0c;与Python等软件编程语言相比&#xff0c;公开可用…

作者头像 李华
网站建设 2026/5/25 22:37:26

ComfyUI-WD14-Tagger:让AI为你自动标注图片,工作效率提升500%

ComfyUI-WD14-Tagger&#xff1a;让AI为你自动标注图片&#xff0c;工作效率提升500% 【免费下载链接】ComfyUI-WD14-Tagger A ComfyUI extension allowing for the interrogation of booru tags from images. 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-WD14-Tag…

作者头像 李华
网站建设 2026/5/25 22:37:17

Windows窗口置顶神器:让重要信息永远在最前面

Windows窗口置顶神器&#xff1a;让重要信息永远在最前面 【免费下载链接】AlwaysOnTop Make a Windows application always run on top 项目地址: https://gitcode.com/gh_mirrors/al/AlwaysOnTop 你是否经常在多个窗口间来回切换&#xff0c;只为查看某个重要的参考文…

作者头像 李华
网站建设 2026/5/25 22:36:21

Agent系列(四):工具调用深度解析——Agent 的手和眼

工具是 Agent 的手和眼 前三篇我们讲了 Agent 的思维框架——ReAct 如何边想边做,Plan-and-Solve 如何先规划再执行。但思维框架再好,Agent 如果只能和 LLM 自己对话,能做的事情极其有限。 工具(Tool)是 Agent 突破语言模型边界的关键。有了工具,Agent 可以: 查询实时…

作者头像 李华