更新记录

1.0.0(2026-09-16) 下载此版本

初版


平台兼容性

uni-app

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - - - 4.4 - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

其他

多语言 暗黑模式 宽屏模式

ModbusTCP 通信工具 (SL-WX-ModbusTcp.js)

基于 HTML5+ plus.android 调用 java.net.Socket 实现的 ModbusTCP 二进制协议通信工具,仅支持 Android App(5+) 环境。非 Android 环境调用任何方法会自动 reject 并弹窗提示。

⚠️ 关于 plus.net 的说明:HTML5+ 的 plus.net 模块仅提供 XMLHttpRequest(HTTP 请求),并不提供原生 TCP Socket API。ModbusTCP 是基于 TCP 的二进制协议,必须使用 Socket。因此本工具通过 plus.android.importClass('java.net.Socket') 调用 Java 原生 Socket 实现,仅 Android 可用;iOS 需要另行开发 uni 原生插件(Objective-C / Swift)。

目录结构

components/SL-WX-ModbusTcp
└── SL-WX-ModbusTcp.js

快速开始

import modbus from '@/components/SL-WX-ModbusTcp/SL-WX-ModbusTcp.js'

// 1. 连接 PLC
await modbus.connect('192.168.1.10', 502, 3000)

// 2. 读 BOOL(线圈,功能码 1)—— 起始地址 1,数量 1
const bools = await modbus.readBool(1, 1, 1, 1)
// → [true]

// 3. 读 INT16(保持寄存器,功能码 3)—— 起始地址 1000,数量 4
const ints = await modbus.readInt(1000, 4, 1, 3)
// → [1234, -5678, 90, 100]

// 4. 读 INT32(占 2 寄存器)—— 地址 1000,字节序 CDAB
const i32 = await modbus.readInt32(1000, 1, 'CDAB', 3)

// 5. 读 FLOAT(占 2 寄存器)—— 地址 2000,字节序 CDAB
const f = await modbus.readFloat(2000, 1, 'CDAB', 3)
// → 3.14

// 6. 写 BOOL(线圈,功能码 5)
await modbus.writeBool(1, true, 1)

// 7. 写 INT16(保持寄存器,功能码 6)
await modbus.writeInt(1000, 12345, 1)

// 8. 写 INT32(占 2 寄存器,功能码 16)
await modbus.writeInt32(1000, 123456789, 'ABCD', 1)

// 9. 写 FLOAT(占 2 寄存器,功能码 16)
await modbus.writeFloat(2000, 3.14159, 'ABCD', 1)

// 10. 断开
await modbus.disconnect()

环境检测

if (!modbus.isApp() || !modbus.isAndroid()) {
  const platform = modbus.getPlatformName() // 'H5' | '微信小程序' | ...
  uni.showModal({ title: '提示', content: `当前为${platform},无法使用 ModbusTCP` })
  return
}

核心特性

  • 完整 ModbusTCP 协议栈:自行构建/解析 MBAP Header(7 字节)+ PDU,支持功能码 1/2/3/4/5/6/16,覆盖线圈、离散输入、保持寄存器、输入寄存器的读写。
  • BOOL / INT16 / INT32 / FLOAT 四种数据类型:读写齐全,INT32 与 FLOAT 自动处理双寄存器拼接。
  • 4 种字节序:ABCD(大端)/ DCBA(小端)/ BADC / CDAB(字交换),适配不同 PLC 厂商的 32 位数据存储顺序。
  • 从站号可配:每次读写可指定 unitId(1~247,默认 1),适配多从站现场。
  • 浮点精度截断readFloat 返回值自动 toFixed(6) 截断 IEEE 754 float32 精度噪声,无需手动处理。
  • 异常响应解析:自动识别 Modbus 异常响应(功能码最高位 = 1),抛出含异常码与中文说明的错误。
  • Transaction ID 校验:每帧递增并校验响应帧的事务标识,防止串帧。
  • 粘包处理:按功能码与请求参数计算预期响应长度,精确读取,无需额外处理粘包。
  • 连接自动清理connect 前自动关闭旧 Socket / InputStream / OutputStream,可安全重复调用。
  • Promise 化 API:所有读写方法返回 Promise,配合 async/await 流畅书写。
  • 平台自动检测:非 Android App 环境调用自动 reject 并弹窗提示,附带 isApp() / isAndroid() / getPlatformName() 环境检测工具。

API 列表

连接 / 断开

connect(host, port, timeout)Promise<true>

建立到 PLC 的 TCP 连接。连接前会自动清理旧连接。

参数 类型 默认值 说明
host String PLC 的 IP 地址,如 '192.168.1.10'
port Number 502 ModbusTCP 标准端口 502
timeout Number 3000 连接超时与读取超时(毫秒),超时后抛出 SocketTimeoutException

disconnect()Promise<true>

断开连接,依次关闭 InputStream、OutputStream、Socket,释放 Java 侧资源。

isConnected()Boolean

同步方法,返回当前是否处于已连接状态。


读取

readBool(addr, count, unitId, funcCode)Promise<Boolean[]>

读取线圈或离散输入,返回布尔值数组。

参数 类型 默认值 说明
addr Number 起始地址(0-based),如 1 表示从第 1 个线圈开始
count Number 1 读取数量,1~2000
unitId Number 1 从站号(1~247)
funcCode Number 1 功能码:1 = 读线圈(可读可写区域),2 = 读离散输入(只读区域)

readInt(addr, count, unitId, funcCode)Promise<Number[]>

读取保持寄存器或输入寄存器,返回有符号 16 位整数数组(-32768~32767)。

参数 类型 默认值 说明
addr Number 起始寄存器地址(0-based),如 1000
count Number 1 读取寄存器数量,1~125
unitId Number 1 从站号(1~247)
funcCode Number 3 功能码:3 = 读保持寄存器(可读可写区域),4 = 读输入寄存器(只读区域)

readInt32(addr, unitId, wordOrder, funcCode)Promise<Number>

读取 32 位有符号整数,占 2 个连续寄存器。

参数 类型 默认值 说明
addr Number 起始寄存器地址(0-based)
unitId Number 1 从站号(1~247)
wordOrder String 'ABCD' 字节序,见「字节序说明」章节。可选:ABCD / DCBA / BADC / CDAB
funcCode Number 3 功能码:3 = 保持寄存器,4 = 输入寄存器

readFloat(addr, unitId, wordOrder, funcCode)Promise<Number>

读取 32 位浮点数,占 2 个连续寄存器。返回值已做 toFixed(6) 精度截断。

参数 类型 默认值 说明
addr Number 起始寄存器地址(0-based)
unitId Number 1 从站号(1~247)
wordOrder String 'ABCD' 字节序,见「字节序说明」章节。可选:ABCD / DCBA / BADC / CDAB
funcCode Number 3 功能码:3 = 保持寄存器,4 = 输入寄存器

写入

writeBool(addr, value, unitId)Promise<true>

写单个线圈(功能码 5)。

参数 类型 默认值 说明
addr Number 线圈地址(0-based)
value Boolean true = ON(发送 0xFF00),false = OFF(发送 0x0000)
unitId Number 1 从站号(1~247)

writeInt(addr, value, unitId)Promise<true>

写单个保持寄存器(功能码 6)。

参数 类型 默认值 说明
addr Number 寄存器地址(0-based)
value Number 有符号 16 位整数,范围 -32768~32767
unitId Number 1 从站号(1~247)

writeInt32(addr, value, wordOrder, unitId)Promise<true>

写 32 位有符号整数,占 2 个连续寄存器(功能码 16)。

参数 类型 默认值 说明
addr Number 起始寄存器地址(0-based)
value Number 有符号 32 位整数,范围 -2147483648~2147483647
wordOrder String 'ABCD' 字节序,见「字节序说明」章节。可选:ABCD / DCBA / BADC / CDAB
unitId Number 1 从站号(1~247)

writeFloat(addr, value, wordOrder, unitId)Promise<true>

写 32 位浮点数,占 2 个连续寄存器(功能码 16)。

参数 类型 默认值 说明
addr Number 起始寄存器地址(0-based)
value Number 浮点数,如 3.14
wordOrder String 'ABCD' 字节序,见「字节序说明」章节。可选:ABCD / DCBA / BADC / CDAB
unitId Number 1 从站号(1~247)

环境检测

isApp()Boolean

同步方法,返回当前是否运行在 App 环境(APP-PLUS 编译条件)。

isAndroid()Boolean

同步方法,返回当前是否为 Android 平台。非 Android 的 App 环境(如 iOS)返回 false

getPlatformName()String

同步方法,返回当前平台名称字符串,用于提示文案。可能的返回值:'H5' / '微信小程序' / '支付宝小程序' / '当前平台'

功能码说明

功能码 名称 数据类型 操作 方法
1 Read Coils BOOL 只读 readBool(addr, count, unitId, 1)
2 Read Discrete Inputs BOOL 只读 readBool(addr, count, unitId, 2)
3 Read Holding Registers INT16 读写 readInt / readInt32 / readFloat (默认 funcCode)
4 Read Input Registers INT16 只读 readInt(addr, count, unitId, 4)
5 Write Single Coil BOOL 只写 writeBool(addr, value, unitId)
6 Write Single Register INT16 只写 writeInt(addr, value, unitId)
16 Write Multiple Registers INT16 只写 writeInt32 / writeFloat(内部使用)

字节序说明

32 位数据(INT32 / FLOAT)占用 2 个连续寄存器,共 4 字节。不同 PLC 的字节排列顺序不同,本工具支持 4 种字节序:

字节序 含义 字节顺序(寄存器 1 高/低 + 寄存器 2 高/低) 适用 PLC
ABCD 大端(高字在前,高字节在前) [A B] [C D] 多数 PLC 默认 / 莫迪康
DCBA 小端(低字在前,低字节在前) [D C] [B A] 部分西门子
BADC 字交换 + 字节交换 [B A] [D C] 部分施耐德
CDAB 字交换(高字在后) [C D] [A B] 部分台达 / 信捷

大多数 PLC 默认 ABCD,调用时可不传 wordOrder 参数(自动取默认值)。具体字节序请参考设备厂商文档。

使用示例

示例 1:读线圈状态(BOOL)

// 读地址 1~8 的 8 个线圈
const bools = await modbus.readBool(1, 8, 1, 1)
// bools = [true, false, true, true, false, false, true, false]

示例 2:读保持寄存器(INT16)

// 读地址 1000~1003 的 4 个保持寄存器
const ints = await modbus.readInt(1000, 4, 1, 3)
// ints = [1234, -5678, 90, 100]

示例 3:读浮点数(FLOAT,32 位)

// 读地址 2000 的 float(占 D2000~D2001 两个寄存器),字节序 ABCD
const f = await modbus.readFloat(2000, 1, 'ABCD', 3)
// f = 3.14

示例 4:写线圈(BOOL)

// 写线圈地址 1 为 ON
await modbus.writeBool(1, true, 1)

// 写线圈地址 2 为 OFF
await modbus.writeBool(2, false, 1)

示例 5:写浮点数(FLOAT,32 位)

// 写 float 到地址 2000(占 D2000~D2001),字节序 ABCD
await modbus.writeFloat(2000, 3.14159, 'ABCD', 1)

示例 6:批量轮询示例

async function poll() {
  try {
    const [bools, ints, f] = await Promise.all([
      modbus.readBool(1, 8, 1, 1),            // 线圈状态
      modbus.readInt(1000, 4, 1, 3),           // 寄存器值
      modbus.readFloat(2000, 1, 'ABCD', 3)     // 浮点数
    ])
    console.log('bools:', bools)
    console.log('ints:', ints)
    console.log('float:', f)
  } catch (e) {
    console.error('轮询失败:', e.message)
    await modbus.disconnect()
  }
}

// 每 1 秒轮询一次
setInterval(poll, 1000)

ModbusTCP 帧结构

MBAP Header(7 字节)

偏移 长度 字段 说明
0 2 Transaction ID 事务标识,递增;响应帧回传相同值
2 2 Protocol ID 协议标识,Modbus 固定为 0x0000
4 2 Length 后续字节数(Unit ID + PDU)
6 1 Unit ID 从站号(1~247)

PDU

偏移 长度 字段 说明
7 1 Func Code 功能码
8+ N Data 数据(请求/响应内容)

异常响应

偏移 长度 字段 说明
7 1 Exception Func 功能码 + 0x80(最高位为 1 标识异常)
8 1 Exception Code 异常码(1=非法功能码,2=非法地址 等)

注意事项

  1. 仅 Android:本工具基于 plus.android.importClass('java.net.Socket'),iOS 不适用。iOS 需要开发 uni 原生插件(Objective-C / Swift 实现 BSD Socket)。

  2. 网络权限:App 需要在 manifest.json 中声明 android.permission.INTERNET 权限(HBuilderX 默认已包含)。

  3. 局域网要求:手机与 PLC 必须在同一局域网,且 PLC 已开启 ModbusTCP 服务(默认端口 502,具体启用方式请参考设备厂商文档)。

  4. 超时设置connect 时设置 timeout(默认 3000ms),同时作为 setSoTimeout 读超时。读不到数据会在 timeout 后抛出 java.net.SocketTimeoutException

  5. 数据范围

    • readBool 单次最多 2000 个
    • readInt 单次最多 125 个寄存器
    • readInt32 / readFloat 实际读 2 个寄存器
    • writeInt 范围 -32768~32767
    • writeInt32 范围 -2147483648~2147483647
  6. 字节序选择:不同 PLC 厂商对 32 位数据在寄存器中的存储顺序不同。多数 PLC 默认 ABCD,若读出的数据明显异常(如很大的随机数),尝试切换为 CDABDCBA

  7. 连接复用connect 前会自动清理旧连接,可重复调用。但建议调用 disconnect 后再 connect,避免资源泄漏。

  8. 异常处理:所有方法 reject 时返回的是原始 Java 异常对象或包装的 Error,可通过 e.message 获取中文错误说明。Modbus 异常响应(如非法地址)会被解析为 'Modbus 异常响应:功能码 0x3,异常码 0x2(非法数据地址)'

  9. 粘包处理:ModbusTCP 响应长度可预期(根据功能码与请求参数可计算),本工具按预期长度读取,无需处理粘包。但若网络异常导致响应残缺,_readBytes 会在读到 EOF(返回 -1)时抛出 '连接已关闭' 错误。

  10. 离开页面:建议在页面 onUnload 生命周期中调用 disconnect(),避免 Socket 资源泄漏。

  11. 浮点精度readFloat 返回值已做 toFixed(6) 精度截断,避免 IEEE 754 float32 的精度噪声(如 3.1400001049041753.14)。如需更高精度可自行处理原始寄存器值。

预览界面说明

预览页面 pages/modbustcp/modbustcp.vue 提供完整的交互式调试面板,包含以下区域:

区域 默认地址 说明
连接配置 IP / 端口 / 从站号 / 字节序(ABCD / DCBA / BADC / CDAB)
读 BOOL 1 功能码 1(线圈)/ 2(离散输入),支持批量读取,结果以 ON/OFF 网格展示
写 BOOL 1 功能码 5,ON / OFF 切换写入
读 INT 1000 功能码 3(保持寄存器)/ 4(输入寄存器),支持批量读取
写 INT 1000 功能码 6(INT16)/ 16(INT32),可切换类型
读 FLOAT 2000 功能码 3,占 2 个寄存器,结果自动截断精度噪声
写 FLOAT 2000 功能码 16,占 2 个寄存器
操作日志 记录最近 50 条操作结果,支持清空

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。