DolphinDB MQTT协议接入:工业设备数据采集

目录

    • 摘要
    • 一、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协议接入:

  1. MQTT协议:轻量级、发布订阅、QoS级别
  2. 插件配置:安装、加载、配置
  3. 连接管理:创建连接、状态监控
  4. 主题订阅:订阅主题、QoS配置
  5. 数据解析:JSON解析、自定义格式、二进制解析
  6. 数据写入:流表写入、分布式表写入、批量优化
  7. 高可用:断线重连、心跳检测、数据缓冲

思考题

  1. MQTT协议有什么优势?
  2. 如何设计高可用的MQTT数据采集系统?
  3. 如何处理MQTT消息丢失问题?

参考资料


相关推荐
Championship.23.241 小时前
Linux 3.0 串口机制深度解析:传统8250驱动与基础RS-232/485支持
linux·运维·服务器
r-t-H1 小时前
Docker进阶与容器编排实践-第三章
运维·docker·容器
啦啦啦~~~3302 小时前
【装机工具】电脑重装系统!office安装管理软件!一键自动化下载、安装、部署Office的办公增强工具
运维·c语言·windows·自动化·电脑
Legend NO242 小时前
从数据中台到 Data Fabric:数据价值落地,终究要回归本质(二)
大数据·运维·fabric
vortex52 小时前
解决 Alpine Linux 虚拟机从 VirtualBox 迁移到 VMware 的内核崩溃问题
linux·运维
qq_白羊座2 小时前
Linux 压缩 / 解压(tar)命令 + 参数详解
linux·运维·github
极客先躯2 小时前
高级java每日一道面试题-2026年02月07日-实战篇[Docker]-如何使用存储插件(如 NFS、Ceph)?
运维·分布式·容器·自动化·文件·插件·高可用
IT探索2 小时前
服务器 BIOS 测试
运维·服务器·网络
hj2862512 小时前
Rsync 数据同步 + Inotify 实时监控 完整版实操笔记3
linux·运维·网络