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

参考资料


相关推荐
荣合技术服务44 分钟前
EMQX mqtt在 Windows 系统上的安装教程
windows·mqtt·emqx
打工仔折腾 AI1 小时前
飞牛OS上用Docker Compose部署ExerciseDiary运动记录并配置远程访问
运维·人工智能·后端·python·docker·容器·ai agent 实战
天远数科1 小时前
零信任架构实战:基于天远运营商三要素简版V即时版查询构建自动化买手实名核验网关
运维·人工智能·架构·自动化
天衍四九-2 小时前
Docker Compose企业实战系列(八·终章):多环境隔离实战,开发/测试/生产一键切换
运维·docker·容器
IT大白鼠2 小时前
搜索系列 · 第 04 篇——部署实操:内网集群落地
运维·elasticsearch·nosql
Elastic 中国社区官方博客2 小时前
使用 Jev 作为 search reranker:基准测试与实现方法
大数据·运维·elasticsearch·全文检索
红红谈说3 小时前
浏览器自动化环境老是起不来?依赖治理与启动自检的一次复盘
运维·自动化·浏览器自动化·进程残留·环境依赖·启动自检·版本比较
赵民勇3 小时前
glib-compile-schemas命令详解
linux·运维
小小、码农4 小时前
〖Linux进程间通信〗IPC全家桶:匿名管道、FIFO、共享内存、消息队列与信号量一篇打通
linux·运维·服务器
阳光九叶草LXGZXJ4 小时前
达梦数据库-学习-67-SSL加密认证
linux·运维·数据库·sql·学习·ssl