滑坡监测通常依赖多种传感器协同工作,包括倾角计、裂缝计、雨量计和GPS位移站。这些设备按照固定频率上报数据,后端需要具备高并发接入、异常识别和实时告警能力。Node.js事件驱动模型适合处理大量短连接和消息推送,下面围绕DeLandslide监测系统给出核心实现。

系统整体架构与数据流设计
DeLandslide监测系统可以划分为采集层、服务层、存储层和展示层。采集层由分布在边坡上的传感器节点组成,它们通过4G或LoRa网关将数据发送到服务端。服务层使用Node.js搭建,负责接收HTTP请求、校验数据格式、判断预警等级并通过Socket.IO实时推送。存储层采用SQLite保存历史位移和雨量记录,便于后续趋势分析。展示层是一个浏览器页面,利用图表库绘制曲线,同时监听WebSocket消息更新预警状态。
传感器数据通常以JSON格式上报,一个典型的数据包包含设备编号、位移量、倾角、降雨量和电池电压。例如设备编号为SLOPE-01的节点可能发送如下结构:deviceId字段用来标识传感器,displacement表示累计位移毫米数,angle表示倾斜角度,rainfall表示小时降雨量。服务端把这些字段解析后写入数据库,再根据规则判断是否需要触发告警。这种分层设计让硬件接入和后端逻辑解耦,后续增加新类型传感器时只需要扩展数据字段,不需要改写核心推送逻辑。
选择Node.js作为服务端的原因在于其非阻塞I/O特性。一个滑坡监测点可能同时连接几十甚至上百个传感器,传统同步模型容易在数据库写入或网络请求处形成瓶颈。Node.js可以在等待磁盘或网络操作时继续处理其他请求,配合Socket.IO的长连接机制,能够把报警信息在毫秒级内广播给所有在线客户端。对于中小规模的地质灾害监测项目,这种单进程架构已经足够稳定,也可以通过PM2启动多个实例来应对更高负载。
搭建数据接收与实时推送服务
首先初始化一个Node.js项目并安装依赖,需要用到express处理HTTP接口,socket.io实现实时通信,以及better-sqlite3完成本地数据存储。服务启动后会创建一个名为delandslide.db的SQLite文件,并在首次运行时自动建立记录表。数据库表的字段与传感器上报结构一一对应,同时增加自增主键和创建时间,方便按时间范围查询。
核心代码如下,它实现了POST /api/sensor/data接口,接收传感器数据后立即写入数据库,并根据位移和倾角是否超过阈值决定推送普通更新还是滑坡告警。Socket.IO服务通过io.emit把消息分发给所有已连接的浏览器客户端。
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const Database = require('better-sqlite3');
const db = new Database('delandslide.db');
db.exec(`CREATE TABLE IF NOT EXISTS records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT NOT NULL,
displacement REAL,
angle REAL,
rainfall REAL,
created_at TEXT DEFAULT (datetime('now','localtime'))
)`);
const app = express();
app.use(express.json());
const server = http.createServer(app);
const io = socketIo(server, { cors: { origin: '*' } });
const WARN_DISPLACEMENT = 5.0;
const WARN_ANGLE = 1.5;
app.post('/api/sensor/data', (req, res) => {
const { deviceId, displacement = 0, angle = 0, rainfall = 0 } = req.body;
if (!deviceId) {
return res.status(400).json({ ok: false, message: '缺少设备编号' });
}
const stmt = db.prepare('INSERT INTO records (device_id, displacement, angle, rainfall) VALUES (?, ?, ?, ?)');
stmt.run(deviceId, displacement, angle, rainfall);
const level = displacement > WARN_DISPLACEMENT || angle > WARN_ANGLE ? 'warning' : 'normal';
const payload = { deviceId, displacement, angle, rainfall, level, time: new Date().toISOString() };
if (level === 'warning') {
io.emit('landslide-alert', payload);
} else {
io.emit('sensor-update', payload);
}
res.json({ ok: true, level });
});
app.get('/api/records', (req, res) => {
const rows = db.prepare('SELECT * FROM records ORDER BY id DESC LIMIT 50').all();
res.json(rows);
});
io.on('connection', (socket) => {
console.log('客户端已连接:' + socket.id);
});
server.listen(3000, () => {
console.log('DeLandslide 监测服务运行在 3000 端口');
});
这段代码中,displacement > WARN_DISPLACEMENT和angle > WARN_ANGLE是两个基础判断条件,只要满足其中一个,服务端就会把级别标记为warning并通过landslide-alert事件广播。如果数据正常,则广播sensor-update事件,前端可以据此刷新实时曲线。为了让数据库操作不会阻塞事件循环,实际项目中还可以把数据库写入放到队列中异步执行,但中小规模场景下直接同步写入已经足够快。
滑坡预警阈值判断与分级策略
单一阈值判断只能区分正常和异常,难以适应不同风险等级的通知需求。实际滑坡监测中,位移速率、累计位移和降雨强度往往需要组合评估。例如持续降雨会导致土壤含水率升高,即使当前位移不大,也可能在短时间内发生突变。因此预警逻辑最好采用多级策略,根据多个指标综合判断风险等级。
下面给出一个简单的分级函数,它把位移、倾角和雨量分别设置不同档位,只要任意指标达到更高一级阈值,就返回对应颜色预警。这样后端可以在写入数据后调用该函数,把返回的级别附加到推送消息中,方便前端显示不同颜色的告警卡片。
function evaluateRisk(displacement, angle, rainfall) {
if (displacement >= 20 || angle >= 5 || rainfall >= 100) {
return '红色预警';
}
if (displacement >= 10 || angle >= 3 || rainfall >= 60) {
return '橙色预警';
}
if (displacement >= 5 || angle >= 1.5 || rainfall >= 30) {
return '黄色预警';
}
return '正常';
}
实际部署时,这些阈值不能直接照搬,需要根据边坡的地质条件、历史位移数据和当地降雨特征进行调整。比如某些地区常年降雨量大,雨量阈值可以适当提高,避免频繁误报。反过来,对于已经出现明显裂缝的边坡,位移阈值应该调低,以便更早发现加速变形。预警级别可以通过配置表或环境变量管理,而不是硬编码在代码中,这样现场维护人员无需修改程序就能调整规则。
历史数据查询与前端可视化
前端大屏通常需要同时展示实时数据和历史趋势。服务端已经提供了/api/records接口,返回最近50条记录。页面加载时可以先请求该接口绘制初始曲线,之后通过Socket.IO监听sensor-update事件把新数据追加到图表尾部。当收到landslide-alert事件时,页面应触发醒目的视觉提醒,比如红色边框闪烁或声音报警。
一个简化的前端页面如下,它引入Socket.IO客户端脚本,连接服务端后分别处理两个事件。landslide-alert会把状态栏文字改为预警信息,sensor-update则在控制台输出最新数据。实际项目中可以把这些数据交给Chart.js或ECharts进行曲线渲染。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DeLandslide 监测大屏</title>
</head>
<body>
<h1>滑坡监测实时数据</h1>
<div id="status">正常</div>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
socket.on('landslide-alert', function (data) {
document.getElementById('status').innerText = '预警:' + data.deviceId;
});
socket.on('sensor-update', function (data) {
console.log(data);
});
</script>
</body>
</html>
部署时需要注意Socket.IO客户端脚本路径要与服务端保持一致,如果前端页面由Nginx托管,还需要配置反向代理把/socket.io/请求转发到Node.js进程。传感器接入接口建议增加Token鉴权,防止未授权设备向系统写入伪造数据。服务端可以使用PM2守护进程,保证异常退出后自动拉起,从而让DeLandslide监测系统在无人值守环境下持续运行。
Node.js滑坡监测DeLandslide修改时间:2026-08-20 20:35:46