用Linux构建边缘数据采集网关:多传感器数据聚合与MQTT上云方案
工业现场的设备协议五花八门——Modbus RTU走RS485、4-20mA模拟量、数字IO干接点、还有各种私有串口协议。把这些异构数据统一采集、预处理后再推上云端,正是边缘数据采集网关的核心价值。本文用一个基于ARM Linux(如RK3568/AM335x)的实际方案,演示如何用C/Python完成多传感器数据聚合,并通过MQTT桥接到阿里云/华为云。
硬件接口抽象:一切皆文件
在Linux下,传感器接入无非三类:
串口设备:/dev/ttyS*或/dev/ttyUSB*,用于Modbus RTU/自定义协议
I2C设备:/dev/i2c-*,温度/湿度传感器
GPIO/ADC:通过/sys/class/gpio或/sys/bus/iio/devices
第一步是编写统一的设备抽象层,将不同协议的读取封装成标准函数指针:
typedef struct {
int (*init)(void *handle);
int (*read)(void *handle, float *value);
void (*deinit)(void *handle);
} sensor_driver_t;
例如Modbus温度传感器的实现:
int modbus_read(void *handle, float *temp) {
uint16_t reg;
modbus_read_registers((modbus_t*)handle, 0, 1, ®);
*temp = reg * 0.01; // 假设精度0.01°C
return 0;
}
这样上层逻辑只需遍历传感器链表,调用read即可完成轮询。
数据聚合:环形缓冲区 + 滑动窗口
原始传感器数据噪声大,网关层面通常要做滤波和聚合。推荐使用固定大小的环形缓冲区,每采集一轮数据就更新滑动窗口均值:
import collections
class SensorAggregator:
def __init__(self, window_size=10):
self.buffer = collections.deque(maxlen=window_size)
def push(self, value):
self.buffer.append(value)
@property
def average(self):
if not self.buffer: return 0
return sum(self.buffer) / len(self.buffer)
对于高频采样(如振动传感器),还可以加入中值滤波或一阶低通滤波,在网关端减轻云端压力。
MQTT上云:mosquitto + TLS加密
选择Mosquitto作为MQTT Broker(也可用EMQX Nano)。网关作为客户端发布JSON payload到特定Topic:
import paho.mqtt.client as mqtt
import json
client = mqtt.Client(client_id="gateway_001")
client.tls_set("/etc/mosquitto/certs/ca.crt") # 证书路径
client.username_pw_set("device", "password")
client.connect("iot.aliyun.com", 8883, 60)
while True:
data = {
"timestamp": time.time(),
"sensors": {
"temperature": agg_temp.average,
"humidity": agg_hum.average,
"pressure": pressure_raw
}
}
client.publish("factory/line1/gateway01", json.dumps(data), qos=1)
time.sleep(5) # 5秒上报一次
关键点:
使用TLS双向认证,防止非法设备接入
QoS设为1确保至少一次送达
Payload采用扁平JSON,方便云端时序数据库写入
离线缓存与断网续传
工业现场网络不稳定,网关必须具备本地缓存能力。推荐SQLite轻量数据库:
CREATE TABLE sensor_cache (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp REAL,
payload TEXT,
sent INTEGER DEFAULT 0
);
每次采集先写入SQLite,后台线程定时扫描未发送记录并尝试推送。成功后将sent标记为1,定期清理历史数据。这样即使断网数小时,数据也不会丢失。
性能调优:避免资源过载
ARM Linux网关资源有限,需注意几点:
轮询周期:根据传感器数量合理设置,一般100ms~1s,避免CPU满载
内存泄漏:使用Valgrind或AddressSanitizer检测,特别是C语言实现的Modbus驱动
日志管理:使用logrotate切割日志,防止SD卡写爆
看门狗:启用硬件看门狗,防止程序卡死导致网关失联
# 启用系统看门狗
echo 1 > /dev/watchdog
# 或在应用层周期性喂狗
#include <linux/watchdog.h>
写在最后
这套方案已在多个产线落地:Modbus RTU采集温湿度、PLC通过以太网传递产量计数、IO模块监控急停信号——全部通过同一网关汇聚,经MQTT上传至工厂MES系统。关键在于抽象层的设计,让新增传感器只需实现read函数,其余逻辑完全复用。从设备树到MQTT,Linux的边缘网关之路,本质上就是把"万物"变成"文件",再把"文件"变成"消息"。





