如何用Node.js实现DeHydroponics水培系统?

来源:站长源码作者:南京GEO公司头衔:草根站长
导读:本期聚焦于南京GEO公司创作的《如何用Node.js实现DeHydroponics水培系统?》,敬请观看详情。把种植槽、营养液桶和补光灯交给代码管理,家庭种植爱好者都很想尝试,但往往卡在软件架构和通信协议上。DeHydroponics 给出了一套基于 Node.js 的实现思路,从传感器数据采集、设备控制到网页监控全部用 JavaScript 完成。本文先介绍整体硬件与软件分层,然后聚焦 Node.js 服务端如何通过 MQTT 接收 ESP32 上报的 pH、EC 和水温数据,再用 SQLite 保存历史记录,并利用 node-cron 定时驱动水泵和光照。最后构建一个 Express 接口和 Socket.IO 实时推送页面,让你随时查看生长环境并手动干预。整个过程不需要额外的后端语言,前端也可以复用同一技术栈,适合快速落地智能种植原型或课程设计。同时会讲解消息校验、异常告警和部署注意事项。

DeHydroponics 并不是一个需要昂贵商业控制器的项目,它的核心思路是把水培装置拆成传感器层、传输层、服务层和展示层。Node.js 作为服务层可以同时处理设备消息、业务逻辑和 Web 接口,省去了多语言切换的麻烦。整个系统围绕 MQTT 消息驱动,传感器数据从 ESP32 端发出,经过 Broker 到达 Node.js 服务端,服务端负责解析、存储、判断阈值,并把控制指令反向发布给执行设备。

如何用Node.js实现DeHydroponics水培系统?

一、硬件选型与系统分层

水培装置需要持续监测的营养液参数通常包括温度、pH 值和 EC 值(电导率),有时还要加上环境光照和空气温湿度。执行机构则包含水泵、气泵、补光灯和电磁阀。在硬件端,使用 ESP32 作为主控,通过模拟输入或 I2C 接口读取各类传感器,再通过 Wi-Fi 把数据发布到 MQTT Broker。ESP32 的模拟输入精度有限,pH 和 EC 传感器需要经过校准并配合温度补偿,这部分通常需要在固件层完成。

系统分层上,硬件层负责传感器采样和继电器开关,可以用 Arduino IDE 或 PlatformIO 编写 C++ 固件。传输层选用 MQTT 协议,主题设计遵循统一前缀,例如 dehydro/sensor/ph、dehydro/sensor/ec、dehydro/actuator/pump。服务层就是本文的主角 Node.js,展示层则是浏览器页面。MQTT 相比 HTTP 更适合物联网场景,因为它是轻量级的发布订阅协议,支持断线重连和低带宽通信,而且 Broker 可以使用开源的 Mosquitto,部署成本很低。

为什么不让 Node.js 直接操作 GPIO?因为服务端通常运行在树莓派、NAS 或云服务器上,而传感器和执行机构分布在种植架附近。两者物理分离后,采用 MQTT 指令下发是最自然的方式。设备端订阅自己的执行主题,收到 JSON 指令后驱动继电器,并在完成后回传状态。这样即使服务端重启,设备端依然可以按照最后一次指令维持运行。

二、Node.js 服务端核心:MQTT 订阅与数据存储

服务端首先需要安装依赖,包括 mqtt、express、sqlite3、node-cron 和 socket.io。入口文件中连接 MQTT Broker,订阅传感器主题。消息回调里需要做 JSON 解析和异常捕获,因为设备端可能发送不完整的数据包。

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://127.0.0.1:1883');

client.on('connect', () => {
  console.log('MQTT connected');
  client.subscribe('dehydro/sensor/#', { qos: 1 });
});

client.on('message', (topic, message) => {
  try {
    const payload = JSON.parse(message.toString());
    console.log(topic, payload);
    saveSensorData(topic, payload);
  } catch (err) {
    console.error('invalid message', err.message);
  }
});

数据存储选用 SQLite 的原因在于它轻量、无需独立数据库进程,单文件即可保存,适合单机部署和原型验证。建表时按传感器类型和数值分开存储,同时保留时间戳和单位。后续如果数据量增大,可以平滑迁移到 PostgreSQL 或时序数据库 InfluxDB。

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('./dehydro.db');

db.serialize(() => {
  db.run(`CREATE TABLE IF NOT EXISTS sensor_readings (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    sensor_type TEXT NOT NULL,
    value REAL NOT NULL,
    unit TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )`);
});

function saveSensorData(topic, payload) {
  const type = topic.split('/').pop();
  const stmt = db.prepare('INSERT INTO sensor_readings (sensor_type, value, unit) VALUES (?, ?, ?)');
  stmt.run(type, payload.value, payload.unit || '');
  stmt.finalize();
}

MQTT 消息可能因为网络波动出现乱序或重复,服务端不能盲目信任每一条数据。可以在保存前做数值范围过滤,例如 pH 值合理范围是 0 到 14,EC 值通常不会超过 5000。超出范围的数据直接丢弃,并记录一条警告日志。对于时间戳,最好以服务端接收时间为准,避免设备端时钟不准带来的混乱。

三、自动控制:定时任务与反向指令

水培系统的日常维护离不开定时任务,例如补光灯每天固定开关、营养液循环泵每隔几小时运行一段时间。Node.js 的 node-cron 模块提供了类似 crontab 的表达式能力,可以方便地定义这些周期任务。下面代码展示了光照控制和水泵循环的典型配置。

const cron = require('node-cron');

cron.schedule('0 6 * * *', () => {
  client.publish('dehydro/actuator/light', JSON.stringify({ state: 'on' }));
});

cron.schedule('0 22 * * *', () => {
  client.publish('dehydro/actuator/light', JSON.stringify({ state: 'off' }));
});

cron.schedule('0 */2 * * *', () => {
  client.publish('dehydro/actuator/pump', JSON.stringify({ state: 'on', duration: 900 }));
});

这里的关键设计是把设备端做成指令执行器,而不是由服务端直接控制 GPIO。设备端收到 dehydro/actuator/pump 的消息后,根据 duration 字段打开继电器,并在倒计时结束后自动关闭。这样即使 MQTT 连接暂时中断,水泵也不会一直运行,安全性更高。设备端还可以在关闭时回传一条状态消息,服务端据此更新界面中的设备状态。

除了定时控制,异常告警也是自动控制的重要部分。例如当 pH 值低于 5.5 或高于 7.5 时,服务端可以触发告警逻辑。最简单的做法是发送邮件或调用 Webhook,同时发布一条紧急指令关闭营养液循环泵。阈值判断可以写在 MQTT 消息回调中,也可以定期从数据库查询最新值。前者及时性更好,后者可以避免瞬时波动造成的误报。

四、Web 控制台与实时监控

Express 负责提供 RESTful API,前端页面通过接口获取历史数据和设备状态。下面是一个返回最新传感器记录的接口示例,它从 SQLite 中查询最近 10 条数据并返回 JSON。生产环境中建议增加分页参数和身份验证。

const express = require('express');
const app = express();
app.use(express.json());

app.get('/api/sensors/latest', (req, res) => {
  db.all('SELECT sensor_type, value, unit, created_at FROM sensor_readings ORDER BY id DESC LIMIT 10', (err, rows) => {
    if (err) return res.status(500).json({ error: err.message });
    res.json(rows);
  });
});

app.listen(3000, () => console.log('API on 3000'));

实时监控则需要 Socket.IO,它能把 MQTT 收到的新数据立即推送到浏览器。在 MQTT 消息回调中调用 io.emit('sensor-data', payload),前端监听同名事件并更新页面。这样可以避免前端频繁轮询接口,减少服务端压力。前端代码可以非常简洁,下面是一个基本页面。

<!DOCTYPE html>
<html>
<body>
  <h3>实时环境数据</h3>
  <div id="data"></div>
  <script src="/socket.io/socket.io.js"></script>
  <script>
    const socket = io();
    socket.on('sensor-data', (data) => {
      document.getElementById('data').innerText = JSON.stringify(data);
    });
  </script>
</body>
</html>

部署时可以使用 PM2 守护 Node.js 进程,配合 Nginx 做反向代理和 HTTPS 加密。传感器数据属于隐私信息,不应该在公网上明文传输。如果希望进一步可视化历史趋势,可以把数据同时写入 InfluxDB,再用 Grafana 展示,但这样会增加运维复杂度,对于个人项目而言 SQLite 配合简单的折线图已经足够。

整个 DeHydroponics 项目把水培控制的核心逻辑集中在 Node.js 服务端,设备端保持简单,前端保持轻量。这种分层方式不仅让系统容易调试,也为后续扩展更多传感器或执行器留出了空间。只要理解了 MQTT 消息流和定时任务的配合,就能基于这套骨架快速搭建自己的智能种植环境。

Node.js水培系统DeHydroponics修改时间:2026-09-19 18:09:48

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0919/59337.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。