目录
-
- 摘要
- 一、MQTT协议概述
-
- [1.1 什么是MQTT](#1.1 什么是MQTT)
- [1.2 MQTT特点](#1.2 MQTT特点)
- [1.3 MQTT在工业物联网中的应用](#1.3 MQTT在工业物联网中的应用)
- [二、DolphinDB MQTT插件](#二、DolphinDB MQTT插件)
-
- [2.1 插件安装](#2.1 插件安装)
- [2.2 插件配置](#2.2 插件配置)
- 三、MQTT连接管理
-
- [3.1 创建连接](#3.1 创建连接)
- [3.2 连接参数](#3.2 连接参数)
- [3.3 连接状态监控](#3.3 连接状态监控)
- 四、主题订阅
-
- [4.1 订阅主题](#4.1 订阅主题)
- [4.2 取消订阅](#4.2 取消订阅)
- [4.3 QoS级别](#4.3 QoS级别)
- 五、数据解析
-
- [5.1 JSON数据解析](#5.1 JSON数据解析)
- [5.2 自定义格式解析](#5.2 自定义格式解析)
- [5.3 二进制数据解析](#5.3 二进制数据解析)
- 六、数据写入
-
- [6.1 实时写入流表](#6.1 实时写入流表)
- [6.2 写入分布式表](#6.2 写入分布式表)
- [6.3 批量写入优化](#6.3 批量写入优化)
- 七、高可用部署
-
- [7.1 断线重连](#7.1 断线重连)
- [7.2 心跳检测](#7.2 心跳检测)
- [7.3 数据缓冲](#7.3 数据缓冲)
- 八、实战案例
-
- [8.1 工业设备数据采集系统](#8.1 工业设备数据采集系统)
- 九、总结
- 参考资料
摘要
本文深入讲解DolphinDB MQTT协议接入技术。从MQTT协议原理到插件配置,从主题订阅到数据解析,从实时写入到高可用部署,全面介绍MQTT数据采集的核心方法。通过丰富的代码示例,帮助读者掌握工业设备数据采集的核心技能。
一、MQTT协议概述
1.1 什么是MQTT
MQTT(Message Queuing Telemetry Transport)是轻量级消息传输协议:
#mermaid-svg-hRuG5DkOMmH42U5b{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hRuG5DkOMmH42U5b .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hRuG5DkOMmH42U5b .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hRuG5DkOMmH42U5b .error-icon{fill:#552222;}#mermaid-svg-hRuG5DkOMmH42U5b .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hRuG5DkOMmH42U5b .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hRuG5DkOMmH42U5b .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hRuG5DkOMmH42U5b .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hRuG5DkOMmH42U5b .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hRuG5DkOMmH42U5b .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hRuG5DkOMmH42U5b .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hRuG5DkOMmH42U5b .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hRuG5DkOMmH42U5b .marker.cross{stroke:#333333;}#mermaid-svg-hRuG5DkOMmH42U5b svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hRuG5DkOMmH42U5b p{margin:0;}#mermaid-svg-hRuG5DkOMmH42U5b .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hRuG5DkOMmH42U5b .cluster-label text{fill:#333;}#mermaid-svg-hRuG5DkOMmH42U5b .cluster-label span{color:#333;}#mermaid-svg-hRuG5DkOMmH42U5b .cluster-label span p{background-color:transparent;}#mermaid-svg-hRuG5DkOMmH42U5b .label text,#mermaid-svg-hRuG5DkOMmH42U5b span{fill:#333;color:#333;}#mermaid-svg-hRuG5DkOMmH42U5b .node rect,#mermaid-svg-hRuG5DkOMmH42U5b .node circle,#mermaid-svg-hRuG5DkOMmH42U5b .node ellipse,#mermaid-svg-hRuG5DkOMmH42U5b .node polygon,#mermaid-svg-hRuG5DkOMmH42U5b .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hRuG5DkOMmH42U5b .rough-node .label text,#mermaid-svg-hRuG5DkOMmH42U5b .node .label text,#mermaid-svg-hRuG5DkOMmH42U5b .image-shape .label,#mermaid-svg-hRuG5DkOMmH42U5b .icon-shape .label{text-anchor:middle;}#mermaid-svg-hRuG5DkOMmH42U5b .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hRuG5DkOMmH42U5b .rough-node .label,#mermaid-svg-hRuG5DkOMmH42U5b .node .label,#mermaid-svg-hRuG5DkOMmH42U5b .image-shape .label,#mermaid-svg-hRuG5DkOMmH42U5b .icon-shape .label{text-align:center;}#mermaid-svg-hRuG5DkOMmH42U5b .node.clickable{cursor:pointer;}#mermaid-svg-hRuG5DkOMmH42U5b .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hRuG5DkOMmH42U5b .arrowheadPath{fill:#333333;}#mermaid-svg-hRuG5DkOMmH42U5b .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hRuG5DkOMmH42U5b .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hRuG5DkOMmH42U5b .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hRuG5DkOMmH42U5b .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hRuG5DkOMmH42U5b .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hRuG5DkOMmH42U5b .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hRuG5DkOMmH42U5b .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hRuG5DkOMmH42U5b .cluster text{fill:#333;}#mermaid-svg-hRuG5DkOMmH42U5b .cluster span{color:#333;}#mermaid-svg-hRuG5DkOMmH42U5b div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hRuG5DkOMmH42U5b .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hRuG5DkOMmH42U5b rect.text{fill:none;stroke-width:0;}#mermaid-svg-hRuG5DkOMmH42U5b .icon-shape,#mermaid-svg-hRuG5DkOMmH42U5b .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hRuG5DkOMmH42U5b .icon-shape p,#mermaid-svg-hRuG5DkOMmH42U5b .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hRuG5DkOMmH42U5b .icon-shape .label rect,#mermaid-svg-hRuG5DkOMmH42U5b .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hRuG5DkOMmH42U5b .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hRuG5DkOMmH42U5b .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hRuG5DkOMmH42U5b :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} MQTT架构
设备/传感器
MQTT Broker
设备/传感器
设备/传感器
订阅者1
订阅者2
DolphinDB
1.2 MQTT特点
| 特点 | 说明 |
|---|---|
| 轻量级 | 协议简单,开销小 |
| 发布订阅 | 一对多通信 |
| QoS级别 | 消息质量保证 |
| 持久会话 | 断线重连 |
1.3 MQTT在工业物联网中的应用
| 场景 | 说明 |
|---|---|
| 设备数据采集 | 传感器数据上报 |
| 远程控制 | 设备指令下发 |
| 状态监控 | 设备状态推送 |
| 告警通知 | 异常告警推送 |
二、DolphinDB MQTT插件
2.1 插件安装
python
// 检查插件是否已加载
getLoadedPlugins()
// 加载MQTT插件
loadPlugin("mqtt")
// 查看插件函数
mqtt::getPluginFunctions()
2.2 插件配置
python
// MQTT连接配置
config = dict(STRING, ANY, [
["host", "localhost"],
["port", 1883],
["clientId", "dolphindb_client"],
["username", "admin"],
["password", "password"],
["keepAlive", 60],
["cleanSession", true]
])
三、MQTT连接管理
3.1 创建连接
python
// 创建MQTT连接
conn = mqtt::connect("localhost", 1883, "dolphindb_client")
// 查看连接状态
mqtt::getStatus(conn)
// 断开连接
mqtt::disconnect(conn)
3.2 连接参数
python
// 完整连接参数
conn = mqtt::connect(
"localhost", // broker地址
1883, // 端口
"dolphindb_client", // 客户端ID
"admin", // 用户名
"password", // 密码
60, // keepAlive时间(秒)
true // cleanSession
)
3.3 连接状态监控
python
// 监控连接状态
def monitorConnection(conn) {
status = mqtt::getStatus(conn)
if (status == "connected") {
print("MQTT连接正常")
} else {
print("MQTT连接异常: " + status)
}
}
monitorConnection(conn)
四、主题订阅
4.1 订阅主题
python
// 创建流表接收数据
share streamTable(1:0,
`device_id`timestamp`temperature`humidity,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE]) as mqtt_stream
// 订阅MQTT主题
mqtt::subscribe(conn, "sensor/data", mqtt_stream)
// 订阅多个主题
mqtt::subscribe(conn, "sensor/temperature", temp_stream)
mqtt::subscribe(conn, "sensor/humidity", humid_stream)
// 订阅通配符主题
mqtt::subscribe(conn, "sensor/+/data", mqtt_stream) // + 单级通配符
mqtt::subscribe(conn, "sensor/#", mqtt_stream) // # 多级通配符
4.2 取消订阅
python
// 取消订阅
mqtt::unsubscribe(conn, "sensor/data")
// 取消所有订阅
mqtt::unsubscribeAll(conn)
4.3 QoS级别
python
// QoS级别说明
// QoS 0: 最多一次,可能丢失
// QoS 1: 至少一次,可能重复
// QoS 2: 恰好一次,保证送达
// 订阅时指定QoS
mqtt::subscribe(conn, "sensor/data", mqtt_stream, 1) // QoS 1
五、数据解析
5.1 JSON数据解析
python
// 创建JSON解析流表
share streamTable(1:0,
`device_id`timestamp`temperature`humidity,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE]) as json_stream
// JSON解析函数
def parseJsonData(jsonStr) {
data = parseJson(jsonStr)
return table(
data.device_id as device_id,
data.timestamp as timestamp,
data.temperature as temperature,
data.humidity as humidity
)
}
// 订阅并解析JSON
mqtt::subscribe(conn, "sensor/json", json_stream,
def(msg) {
parseJsonData(msg)
})
5.2 自定义格式解析
python
// 自定义格式:逗号分隔
// 格式:device_id,timestamp,temperature,humidity
def parseCsvData(csvStr) {
parts = split(csvStr, ",")
return table(
parts[0] as device_id,
timestamp(parts[1]) as timestamp,
double(parts[2]) as temperature,
double(parts[3]) as humidity
)
}
// 订阅并解析
mqtt::subscribe(conn, "sensor/csv", csv_stream, parseCsvData)
5.3 二进制数据解析
python
// 二进制数据解析
def parseBinaryData(binaryData) {
// 假设二进制格式:
// 前4字节:device_id (int32)
// 后8字节:temperature (double)
// 后8字节:humidity (double)
deviceId = parseInt32(binaryData, 0)
temperature = parseDouble(binaryData, 4)
humidity = parseDouble(binaryData, 12)
return table(
deviceId as device_id,
now() as timestamp,
temperature as temperature,
humidity as humidity
)
}
六、数据写入
6.1 实时写入流表
python
// 创建流表
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE]) as sensor_stream
// 启用持久化
enableTablePersistence(sensor_stream, true, true, 1000000)
// 订阅MQTT写入流表
mqtt::subscribe(conn, "sensor/data", sensor_stream)
6.2 写入分布式表
python
// 创建分布式表
db = database("dfs://mqtt_db", VALUE, 1..1000)
schema = table(1:0, `device_id`timestamp`temperature`humidity,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `sensor_data, `device_id)
// 创建流表
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE]) as mqtt_stream
// 订阅流表写入分布式表
subscribeTable(, "mqtt_stream", "persist", -1,
def(msg) {
loadTable("dfs://mqtt_db", "sensor_data").append!(msg)
}, 10000, 5000)
// 订阅MQTT
mqtt::subscribe(conn, "sensor/data", mqtt_stream)
6.3 批量写入优化
python
// 批量写入配置
// batchSize: 批量大小
// throttle: 节流时间(毫秒)
subscribeTable(, "mqtt_stream", "batch_persist", -1,
def(msg) {
loadTable("dfs://mqtt_db", "sensor_data").append!(msg)
},
10000, // batchSize: 10000条
5000) // throttle: 5秒
七、高可用部署
7.1 断线重连
python
// 断线重连配置
def connectWithRetry(host, port, clientId, maxRetries = 5) {
retries = 0
while (retries < maxRetries) {
try {
conn = mqtt::connect(host, port, clientId)
print("MQTT连接成功")
return conn
} catch (ex) {
retries += 1
print("连接失败,重试 " + string(retries) + "/" + string(maxRetries))
sleep(5000) // 等待5秒重试
}
}
throw "MQTT连接失败"
}
// 使用
conn = connectWithRetry("localhost", 1883, "dolphindb_client")
7.2 心跳检测
python
// 心跳检测函数
def heartbeat(conn, interval = 30) {
while (true) {
status = mqtt::getStatus(conn)
if (status != "connected") {
print("连接断开,尝试重连...")
// 重连逻辑
}
sleep(interval * 1000)
}
}
// 启动心跳(异步)
submitJob("mqtt_heartbeat", "MQTT心跳", def() { heartbeat(conn) })
7.3 数据缓冲
python
// 数据缓冲:断线时缓存数据
share table(100000:0,
`device_id`timestamp`temperature`humidity,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE]) as buffer_table
// 写入时先写缓冲
def writeToBuffer(data) {
buffer_table.append!(data)
}
// 定时从缓冲写入分布式表
def flushBuffer() {
data = select * from buffer_table
if (data.rows() > 0) {
loadTable("dfs://mqtt_db", "sensor_data").append!(data)
truncate(buffer_table)
}
}
// 定时任务
scheduleJob("flush_buffer", "刷新缓冲", flushBuffer,
00:01, 2024.01.01, 2030.12.31, 'D')
八、实战案例
8.1 工业设备数据采集系统
python
// ========== 工业设备数据采集系统 ==========
// 1. 创建分布式表
db = database("dfs://iot_mqtt_db", VALUE, 1..1000)
schema = table(1:0,
`device_id`timestamp`temperature`humidity`pressure`vibration,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `device_data, `device_id)
// 2. 创建流表
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity`pressure`vibration,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, DOUBLE]) as mqtt_stream
// 3. 启用持久化
enableTablePersistence(mqtt_stream, true, true, 1000000)
// 4. 订阅流表写入分布式表
subscribeTable(, "mqtt_stream", "persist", -1,
def(msg) {
loadTable("dfs://iot_mqtt_db", "device_data").append!(msg)
}, 10000, 5000)
// 5. 连接MQTT
conn = mqtt::connect("mqtt-broker.local", 1883, "dolphindb_iot")
// 6. 订阅主题
mqtt::subscribe(conn, "factory/+/sensor", mqtt_stream)
// 7. 监控函数
def monitorMqtt() {
print("=== MQTT监控 ===")
print("连接状态: " + mqtt::getStatus(conn))
print("流表行数: " + string(exec count(*) from mqtt_stream))
t = loadTable("dfs://iot_mqtt_db", "device_data")
print("分布式表行数: " + string(exec count(*) from t))
}
monitorMqtt()
print("工业设备数据采集系统启动完成")
九、总结
本文详细介绍了DolphinDB MQTT协议接入:
- MQTT协议:轻量级、发布订阅、QoS级别
- 插件配置:安装、加载、配置
- 连接管理:创建连接、状态监控
- 主题订阅:订阅主题、QoS配置
- 数据解析:JSON解析、自定义格式、二进制解析
- 数据写入:流表写入、分布式表写入、批量优化
- 高可用:断线重连、心跳检测、数据缓冲
思考题:
- MQTT协议有什么优势?
- 如何设计高可用的MQTT数据采集系统?
- 如何处理MQTT消息丢失问题?