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消息丢失问题?

参考资料


相关推荐
邪修king28 分钟前
Re:Linux系统篇(三十六):进程间通信Chapter3:从匿名管道到命名管道:Linux 进程间通信实战(FIFO 深度解析)
linux·运维·服务器
Tech探索者40 分钟前
重装飞牛 NAS,几 KB 的 .bin 够吗?我的备份与恢复全过程
运维·服务器
java_nnnn1 小时前
Linux 学习第一篇:从零认识 Linux,使用 WSL + Ubuntu 搭建学习环境
linux·运维·学习
讯捷蓝达1 小时前
机房突发断电,5 盘 RAID硬盘全部掉线: 急速上门救援,现场4小时华为2288H V5服务器数据完整恢复
运维·服务器·数据库
风翼靓崽1 小时前
磁盘逻辑卷扩容
linux·运维·服务器
Z21-X1 小时前
云原生运维学习笔记:KVM实战——从环境搭建到热迁移的硬核体验
运维·笔记·学习·云原生
论文复现现场1 小时前
RTX 3090 云GPU租赁价格对比:8家平台配置、计费方式与环境测试
linux·运维·人工智能·pytorch·深度学习·云计算·3090
云飞云共享云桌面1 小时前
一台SolidWorks设计服务器多人共享落地方案和配置
运维·服务器·3d·电脑·制造
Pointer Pursuit1 小时前
进程优先级
linux·运维·服务器
skywalk81631 小时前
FreeBSD仿真环境里的Ubuntu linux系统,安装软件的时候不支持snap怎么办?
linux·运维·ubuntu·系统·freebsd