更新记录
1.3.3(2026-09-05)
v1.3.3 修复 Android 端云打包编译错误:补齐 Modbus TCP/RTU 的 Promise 链类型标注,修复 USB 串口相关 Number/Int 转换及 okio 依赖配置,确保 TCP、WebSocket、Modbus TCP/RTU、USB 串口硬件通信在 Android 平台正常编译运行。
1.3.2(2026-09-05)
修复 iot-hardware UTS 插件 Android 端编译错误:补齐 Modbus TCP/RTU Promise 链类型标注,修复 USB 串口 Number/Int 转换与 okio 依赖配置,确保 TCP、WebSocket、Modbus、USB 串口硬件通信功能正常编译打包。
1.3.1(2026-09-04)
修复(Android 原生层,对照三方库源码逐项核验)
- 修复 USB 串口流控:
UsbSerialPort.FLOWCONTROL_NONE 在 usb-serial-for-android 3.7.3 中不存在,改为占位 0(3.7.3 的 setParameters 无流控参数,需流控请用 setDTR()/setRTS())
- 修复 USB 串口连接:移除不存在的
UsbSerialDriver.attach(connection) 调用(3.7.3 的 getPorts() 返回端口已绑定连接)
- 修复串口关闭:移除不存在的
driver.close()(usbPort.close() 已一并关闭 UsbDeviceConnection),并置空引用避免悬挂
- 修复 WebSocket 心跳:移除 okhttp 4.12 不存在的
WebSocket.ping() 协议手动 ping,改为 OkHttpClient.Builder.pingInterval() 自动保活(heartbeatInterval > 0 时启用,0 仍表示禁用),读超时兜底检测保留
- 以上修复均不改变 UTS 层 API 签名,现有调用方无需改动
查看更多
平台兼容性
uni-app(3.8.3)
| Vue2 |
Vue2插件版本 |
Vue3 |
Vue3插件版本 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
Android插件版本 |
iOS |
鸿蒙 |
| √ |
1.0.5 |
√ |
1.0.5 |
- |
- |
- |
- |
√ |
1.0.5 |
√ |
- |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| - |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
uni-app x(3.8.4)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| - |
- |
- |
√ |
- |
- |
iot-hardware
UniApp 硬件通信 UTS 原生插件。提供 TCP 长连接、WebSocket、Modbus TCP / Modbus RTU、USB 转串口 能力,专为工控平板、PDA、物联网设备设计,Android + iOS 双端支持。
特性
- TCP 二进制长连接(子线程非阻塞读写),支持 TLS/SSL 加密
- WebSocket 客户端:文本帧 + 二进制帧收发、okhttp pingInterval 自动保活、断线自动重连(Android 基于 okhttp / iOS 基于 URLSessionWebSocketTask)
- 断线自动重连(指数退避,可设最大次数)
- 心跳保活 + 超时检测 + 读超时(半开连接兜底检测)
- 可配置粘包分包处理器:帧头 / 长度域偏移 / 长度字节数 / 字节序 / 帧格式 / CRC16 校验 均在构造时配置,无需改源码
- Modbus TCP(Promise API)+ Modbus RTU(Android,CRC16 + 静默分帧)
- Modbus 大段自动分片:
readHoldingRegisters 等 count > 125 时自动分片串行读取并合并,无需手动拆分
- Modbus 不连续地址读取:
readHoldingRegistersAt(addresses) / readInputRegistersAt(addresses) 一次批量读取任意地址组合,返回 [{ address, value }]
- 寄存器转换工具:int16 / uint16 / int32 / uint32 / float32 / int64 / uint64 / float64 ↔ 寄存器数组
- USB 转串口 RS232/RS485/TTL(via usb-serial-for-android),支持流控、DTR/RTS 控制、热插拔监听
- 多连接管理器:统一注册/销毁全部实例,页面卸载
destroyAll() 防线程泄漏
- 多回调监听、状态主动查询、
sendAsync() Promise 发送
- 统一错误码(见 错误码表)
环境要求
| 项目 |
要求 |
| HBuilderX |
^4.0.0 |
| Android |
Android 5.0+(TCP / WebSocket / 串口 / Modbus TCP / Modbus RTU 全功能) |
| iOS |
iOS 12+(TCP / WebSocket / Modbus TCP;串口与 Modbus RTU 因 iOS 无 USB Host 能力不支持,构造即抛错) |
| 项目类型 |
uni-app (Vue2/Vue3) |
说明:iOS 原生实现(utssdk/app-ios/SocketClient.swift、WebSocketClient.swift)需在 Mac + HBuilderX 环境下编译验证;Android WebSocket 依赖三方库 okhttp,本地真机运行需在 HBuilderX 配置离线运行环境(含 mavenCentral 依赖缓存),或提交云端打自定义基座。
快速开始
1. 安装
将 iot-hardware 复制到项目 uni_modules/ 目录。
2. 基础 TCP 通信
import { HardwareTcpClient } from '@/uni_modules/iot-hardware'
const client = new HardwareTcpClient({
host: "192.168.1.100",
port: 8899,
reconnect: true,
reconnectInterval: 3000,
heartbeatInterval: 5000,
heartbeatData: HardwareTcpClient.hex2buf("AA BB 00 00")
})
client.onStatus((status) => {
console.log("连接状态:", status)
})
client.onData((buffer) => {
const hex = HardwareTcpClient.buf2hex(buffer)
console.log("收到:", hex)
})
client.onError((msg, code) => {
console.error("错误:", code, msg)
})
client.connect()
// 发送报文
const buf = HardwareTcpClient.hex2buf("AA BB 00 02 01 02 00 00")
client.send(buf)
// 异步发送(Promise)
await client.sendAsync(buf)
// 页面销毁时
// client.destroy()
3. 对接自定义协议(粘包分包 + CRC 配置)
无需改插件源码,构造时配置帧格式即可:
const client = new HardwareTcpClient({
host: "192.168.1.100",
port: 8899,
packet: {
enabled: true, // 启用分包
header: [0xAA, 0xBB], // 帧头
lengthOffset: 2, // 长度域偏移(帧头后第 0 字节)
lengthBytes: 2, // 长度域 2 字节
lengthEndian: "big", // 大端
lengthIncludesHeader: false,
tailLength: 2, // 帧尾 2 字节 CRC
crc: "crc16-modbus", // CRC16-Modbus 校验
crcByteOrder: "little" // CRC 低字节在前
}
})
固定帧长协议(无长度域):
packet: {
frameType: "fixed",
header: [0x50, 0xFF], // 三菱 MC 协议示例
bodyLength: 8, // 固定数据体长度
tailLength: 0
}
设 packet: { enabled: false }(或旧参数 disablePacketHandler: true)可关闭分包,直出原始 TCP/UART 流。
4. Modbus TCP
import { ModbusTcpClient } from '@/uni_modules/iot-hardware'
const modbus = new ModbusTcpClient({
host: "192.168.1.50",
port: 502,
unitId: 1,
responseTimeout: 5000
})
modbus.onStatus((s) => console.log(s))
modbus.connect()
// 读取保持寄存器(Promise API,count > 125 时自动分片串行读取并合并)
const values = await modbus.readHoldingRegisters(0, 10)
console.log("寄存器值:", values)
// 写单个寄存器
await modbus.writeSingleRegister(0, 1234)
// 不连续地址批量读取(自动合并连续段 + 分片),返回 [{ address, value }]
const readings = await modbus.readHoldingRegistersAt([0, 1, 5, 100, 101, 102])
for (const r of readings) {
console.log("地址", r.address, "=", r.value)
}
// 动态修改从站地址
modbus.setUnitId(2)
// 多连接串行化:serialRequests=true 时同一实例请求严格串行(默认 false 并发)
const modbusSerial = new ModbusTcpClient({
host: "192.168.1.50", port: 502, unitId: 1, serialRequests: true
})
modbusSerial.connect()
5. Modbus RTU(Android,经 USB 串口)
import { ModbusRtuClient } from '@/uni_modules/iot-hardware'
const rtu = new ModbusRtuClient({
baudRate: 9600,
dataBits: 8,
stopBits: 0, // 0=1位
parity: 0, // 0=无
unitId: 1,
responseTimeout: 1000,
readIdleTime: 30 // 字符间静默间隔 (ms),默认 30(9600 波特约 3.5 字符时间 ≈ 4ms)
})
rtu.onStatus((s) => console.log("RTU 状态:", s))
rtu.onError((msg, code) => console.error("RTU 错误:", code, msg))
rtu.requestPermission() // 首次使用需授权
rtu.connect() // 授权后自动连接,或直接 connect()
const vals = await rtu.readHoldingRegisters(0, 5)
await rtu.writeSingleRegister(0, 100)
6. USB 转串口(Android)
import { HardwareSerialClient } from '@/uni_modules/iot-hardware'
const serial = new HardwareSerialClient({
baudRate: 9600,
dataBits: 8,
vendorId: 0x1A86, // CH340 示例
productId: 0x7523
})
const devices = serial.listDevices()
console.log("检测到设备:", devices)
serial.onStatus((s) => console.log("串口状态:", s))
serial.onData((buf) => {
console.log("串口收到:", HardwareTcpClient.buf2hex(buf))
})
serial.onDeviceChange((attached, vid, pid) => {
console.log("设备", attached ? "插入" : "拔出", vid, pid)
})
// 首次使用需申请 USB 权限(授权后自动连接)
serial.requestPermission()
serial.connect()
serial.send(new Uint8Array([0xAA, 0xBB, 0x00, 0x01]).buffer as ArrayBuffer)
7. 寄存器转换工具
import { registersToInt16, registersToInt32, registersToFloat32, floatToRegisters, registersToUint64, uint64ToRegisters } from '@/uni_modules/iot-hardware'
const regs = await modbus.readHoldingRegisters(0, 4)
// 前 2 个寄存器为有符号 32 位整数,后 2 个为浮点
const i32 = registersToInt32(regs.slice(0, 2)) // [int32]
const f32 = registersToFloat32(regs.slice(2, 4)) // [float32]
// 写入:把浮点数组转成寄存器再写
const toWrite = floatToRegisters([3.14, -1.5])
await modbus.writeMultipleRegisters(10, toWrite)
// 64 位数值需 4 个寄存器;为避免 BigInt 兼容性问题,以十进制字符串返回/接收
const big = registersToUint64(await modbus.readHoldingRegisters(0, 4)) // ["12345678901234"]
await modbus.writeMultipleRegisters(0, uint64ToRegisters(["12345678901234"]))
8. 多连接管理
import { hardwareManager } from '@/uni_modules/iot-hardware'
const id = hardwareManager.register("plc1", client) // 注册(id 重复时先销毁旧实例)
// hardwareManager.destroy("plc1") // 注销并销毁
// hardwareManager.destroyAll() // 页面卸载:一次性释放全部连接
9. WebSocket 通信
import { HardwareWebSocketClient } from '@/uni_modules/iot-hardware'
const ws = new HardwareWebSocketClient({
url: "ws://192.168.1.100:8080/ws",
protocols: ["binary"], // 可选:子协议
headers: new Map([["Authorization", "token"]]), // 可选:握手请求头
reconnect: true,
heartbeatInterval: 30000, // okhttp pingInterval 自动保活(>0 启用)
readTimeout: 0 // 无数据兜底断线(ms),0=禁用
})
ws.onStatus((status) => { console.log("WS 状态:", status) })
ws.onData((data: ArrayBuffer) => { console.log("WS 二进制消息:", HardwareWebSocketClient.buf2hex(data)) })
ws.onText((text: string) => { console.log("WS 文本消息:", text) })
ws.onError((msg, code) => { console.error("WS 错误:", code, msg) })
ws.connect()
ws.sendText("hello") // 文本帧
ws.send(HardwareWebSocketClient.hex2buf("AA 01 02 BB")) // 二进制帧
ws.disconnect()
API 参考
HardwareWebSocketClient
构造参数
| 参数 |
类型 |
默认值 |
说明 |
| url |
string |
- |
WebSocket 服务地址(ws:// 或 wss://) |
| protocols |
string[] |
[] |
子协议列表(Android 写入 Sec-WebSocket-Protocol 头,iOS 走原生 protocols 参数) |
| headers |
Map\<string,string> |
- |
自定义请求头(仅握手阶段生效) |
| reconnect |
boolean |
true |
是否自动重连 |
| reconnectInterval |
number |
3000 |
重连间隔 (ms) |
| maxReconnectAttempts |
number |
0 |
最大重连次数 (0=不限) |
| heartbeatInterval |
number |
0 |
okhttp pingInterval 自动保活间隔 (ms),0=禁用 |
| connectTimeout |
number |
10000 |
连接超时 (ms) |
| readTimeout |
number |
0 |
读超时 (ms),0=禁用。超过该时长未收到任何帧(文本/二进制/pong)判定断线重连 |
方法
| 方法 |
说明 |
connect() |
发起连接(内部自动重连开关由 reconnect 决定) |
isConnected(): boolean |
是否已连接 |
getStatus(): ConnectStatus |
当前状态 |
send(buffer: ArrayBuffer) |
发送二进制帧 |
sendText(text: string) |
发送文本帧 |
sendAsync(buffer): Promise<void> |
异步发送二进制帧 |
sendTextAsync(text): Promise<void> |
异步发送文本帧 |
disconnect() |
断开连接(停止重连) |
destroy() |
销毁实例并清理回调 |
onStatus(cb) |
状态监听(多回调) |
onData(cb) |
二进制消息监听 |
onText(cb) |
文本消息监听 |
onError(cb) |
错误监听 |
static buf2hex / hex2buf |
十六进制工具 |
HardwareTcpClient
构造参数
| 参数 |
类型 |
默认值 |
说明 |
| host |
string |
- |
服务器 IP |
| port |
number |
- |
服务器端口 |
| reconnect |
boolean |
true |
是否自动重连 |
| reconnectInterval |
number |
3000 |
重连间隔 (ms) |
| maxReconnectAttempts |
number |
0 |
最大重连次数 (0=不限) |
| heartbeatInterval |
number |
5000 |
心跳间隔 (ms) |
| heartbeatData |
ArrayBuffer |
null |
心跳报文,null=禁用心跳 |
| heartbeatTimeout |
number |
15000 |
心跳超时 (ms) |
| connectTimeout |
number |
10000 |
连接超时 (ms) |
| readTimeout |
number |
0 |
读超时 (ms),0=无限;>0 且禁用心跳时兼作半开连接检测 |
| tls |
boolean |
false |
是否启用 TLS/SSL 加密 |
| packet |
PacketConfig |
- |
粘包分包运行时配置(见 protocol.uts) |
| disablePacketHandler |
boolean |
false |
关闭分包直出原始流(等价 packet.enabled=false) |
方法
| 方法 |
说明 |
connect() |
建立连接 |
send(buffer: ArrayBuffer) |
发送二进制数据 |
sendAsync(buffer: ArrayBuffer): Promise<void> |
异步发送 |
disconnect() |
断开(可重连) |
destroy() |
销毁实例(不可再重连) |
isConnected(): boolean |
当前是否已连接 |
getStatus(): ConnectStatus |
获取当前连接状态 |
onStatus(cb) |
监听连接状态变化(可多次调用注册多个回调) |
onData(cb) |
监听数据接收(完整帧) |
onError(cb) |
监听错误 |
static buf2hex(buf): string |
ArrayBuffer → 16进制字符串 |
static hex2buf(hex): ArrayBuffer |
16进制字符串 → ArrayBuffer(支持 AA BB、0xAA,0xBB、AABBCC 等格式) |
onStatus / onData / onError 支持注册多个回调(每次调用追加);传 null 可清空该类回调。
ModbusTcpClient
构造参数(继承 HardwareTcpClient 参数 +)
| 参数 |
类型 |
默认值 |
说明 |
| unitId |
number |
1 |
从站地址 |
| responseTimeout |
number |
5000 |
响应超时 (ms) |
| serialRequests |
boolean |
false |
是否将请求严格串行化(同一实例仅一个在途请求)。true 适合 RS485 半双工或对报文顺序有严格要求的设备 |
方法
| 方法 |
返回 |
说明 |
connect() |
void |
建立连接 |
disconnect() |
void |
断开(可重连) |
destroy() |
void |
销毁实例 |
isConnected() |
boolean |
当前是否已连接 |
getStatus() |
ConnectStatus |
获取当前连接状态 |
setUnitId(id) |
void |
动态修改从站地址(0-247),无需重连 |
onStatus(cb) |
void |
监听连接状态变化 |
onError(cb) |
void |
监听错误 |
readCoils(start, count) |
Promise\<boolean[]> |
FC01 |
readDiscreteInputs(start, count) |
Promise\<boolean[]> |
FC02 |
readHoldingRegisters(start, count) |
Promise\<number[]> |
FC03(count>125 自动分片串行读取合并) |
readInputRegisters(start, count) |
Promise\<number[]> |
FC04(count>125 自动分片串行读取合并) |
readHoldingRegistersAt(addresses) |
Promise\<RegisterReading[]> |
FC03 不连续地址批量读取,返回 [{ address, value }] |
readInputRegistersAt(addresses) |
Promise\<RegisterReading[]> |
FC04 不连续地址批量读取,返回 [{ address, value }] |
writeSingleCoil(addr, value) |
Promise\<void> |
FC05 |
writeSingleRegister(addr, value) |
Promise\<void> |
FC06 |
writeMultipleRegisters(start, values) |
Promise\<void> |
FC10 |
Modbus 请求参数有边界校验:位操作 count 范围 1-2000(>2000 抛参错),寄存器单帧 count 范围 1-125,批量写 1-123 个。大段读取(count>125)由 readHoldingRegisters/readInputRegisters 自动分片处理;不连续地址读取自动合并连续地址段并做合法性/去重/升序处理。
ModbusError
Modbus 方法的 Promise 拒绝时抛出 ModbusError:
| 字段 |
说明 |
| code |
协议异常码为正数(1-11);本地错误为负数(见下表) |
| message |
错误描述 |
| functionCode |
请求的功能码 |
| transId |
事务 ID |
isProtocolError(): boolean |
code > 0 时为从站返回的协议异常 |
本地错误码(负数,与 MODBUS_LOCAL_ERR_* 常量等价):
| 常量 |
值 |
含义 |
| MODBUS_LOCAL_ERR_PARAM |
-1 |
参数错误 |
| MODBUS_LOCAL_ERR_TIMEOUT |
-2 |
响应超时 |
| MODBUS_LOCAL_ERR_DISCONNECTED |
-3 |
连接已断开(含未连接时发起请求) |
| MODBUS_LOCAL_ERR_FC_MISMATCH |
-4 |
响应功能码与请求不匹配 |
| MODBUS_LOCAL_ERR_DESTROYED |
-5 |
实例已销毁 |
| MODBUS_LOCAL_ERR_RESPONSE |
-6 |
响应数据长度与协议不符(如 byteCount 校验失败) |
ModbusRtuClient(Android)
构造参数(继承 HardwareSerialClient 参数 +)
| 参数 |
类型 |
默认值 |
说明 |
| unitId |
number |
1 |
从站地址 |
| responseTimeout |
number |
1000 |
响应超时 (ms) |
| readIdleTime |
number |
30 |
字符间静默间隔 (ms),用于分帧 |
方法
与 ModbusTcpClient 相同(readCoils / readDiscreteInputs / readHoldingRegisters / readInputRegisters / readHoldingRegistersAt / readInputRegistersAt / writeSingleCoil / writeSingleRegister / writeMultipleRegisters / setUnitId),另含串口能力:listDevices() / requestPermission() / connect(index?)。异常同样抛 ModbusError。RTU 请求天然串行(RS485 半双工),大段读取同样自动分片。
HardwareSerialClient(Android)
构造参数
| 参数 |
类型 |
默认值 |
说明 |
| baudRate |
number |
9600 |
波特率 |
| dataBits |
number |
8 |
数据位 |
| stopBits |
number |
0 |
停止位(0=1位,1=1.5位,2=2位) |
| parity |
number |
0 |
校验位(0=无,1=奇,2=偶,3=标记,4=空格) |
| flowControl |
number |
0 |
保留参数:usb-serial 3.7.3 的 setParameters 无流控参数,暂不生效;需流控请用 setDTR()/setRTS() |
| vendorId |
number |
0 |
设备 VID 过滤 (0=不限) |
| productId |
number |
0 |
设备 PID 过滤 (0=不限) |
| reconnect |
boolean |
false |
是否自动重连 |
| reconnectInterval |
number |
3000 |
重连间隔 (ms) |
| maxReconnectAttempts |
number |
3 |
最大重连次数 |
方法
| 方法 |
说明 |
listDevices() |
枚举 USB 串口设备 |
requestPermission() |
申请 USB 权限(授权成功自动连接) |
connect(index?) |
连接指定索引设备(默认第一个) |
isConnected() |
当前是否已连接 |
getStatus() |
获取当前连接状态 |
setDTR(on: boolean) |
设置 DTR 信号 |
setRTS(on: boolean) |
设置 RTS 信号 |
send(buffer: ArrayBuffer) |
发送二进制数据 |
sendAsync(buffer): Promise<void> |
异步发送 |
disconnect() |
断开连接 |
destroy() |
销毁实例 |
onStatus(cb) |
监听连接状态变化(支持多回调) |
onData(cb) |
监听数据接收 |
onError(cb) |
监听错误 |
onDeviceChange(cb) |
监听 USB 设备热插拔 |
协议工具(跨平台,均可直接 import)
| 符号 |
说明 |
crc16Modbus(data): number |
CRC16-Modbus 校验 |
crc16Ccitt(data): number |
CRC16-CCITT 校验 |
PacketConfig |
粘包分包配置类型 |
registersToInt16 / registersToUint16 |
寄存器 → 16 位整数数组 |
registersToInt32 / registersToUint32 / registersToFloat32(regs, byteOrder?) |
每 2 寄存器 → 32 位数值 |
registersToInt64 / registersToUint64 / registersToFloat64(regs, byteOrder?) |
每 4 寄存器 → 64 位数值(int64/uint64 以十进制字符串返回) |
int16ToRegisters / uint16ToRegisters |
16 位整数 → 寄存器 |
int32ToRegisters / floatToRegisters(values, byteOrder?) |
32 位数值 → 寄存器 |
int64ToRegisters / uint64ToRegisters / float64ToRegisters(values, byteOrder?) |
64 位数值 → 寄存器(int64/uint64 接收十进制字符串) |
buildSegments(addresses): AddressSegment[] |
把地址数组去重+升序+合并为连续段(不连续地址读取内部使用) |
RegisterReading |
{ address, value } 类型,不连续地址读取的返回值 |
hardwareManager |
HardwareManager 单例(register / destroy / destroyAll / has / size / ids) |
64 位转换避免使用 BigInt 以保证多端兼容:registersToInt64/registersToUint64 返回十进制 string[],int64ToRegisters/uint64ToRegisters 接收 (string|number)[];float64 仍为 JS number。
错误码
错误码由 onError(msg, code) 的 code 参数返回,常量定义见 utssdk/unierror.uts。
| code |
常量 |
含义 |
| 1001 |
ERROR_TCP_CONNECT_FAILED |
TCP 连接失败(DNS/网络不可达/连接被拒/TLS 握手失败) |
| 1002 |
ERROR_TCP_READ_FAILED |
TCP 读取数据异常(连接中断) |
| 1003 |
ERROR_TCP_SEND_FAILED |
TCP 发送失败(含未连接时发送) |
| 1004 |
ERROR_TCP_RECONNECT_MAX |
TCP 重连已达最大次数 |
| 1005 |
ERROR_TCP_HEARTBEAT_TIMEOUT |
TCP 心跳超时,触发断线重连 |
| 1006 |
ERROR_TCP_READ_TIMEOUT |
TCP 读超时无数据(半开连接兜底检测),触发断线重连 |
| 2001 |
ERROR_SERIAL_NO_PERMISSION |
USB 设备无权限,需先调用 requestPermission() |
| 2002 |
ERROR_SERIAL_CONNECT_FAILED |
串口连接失败 |
| 2003 |
ERROR_SERIAL_READ_FAILED |
串口读取异常 |
| 2004 |
ERROR_SERIAL_SEND_FAILED |
串口发送失败(含未连接时发送) |
| 2005 |
ERROR_SERIAL_RECONNECT_MAX |
串口重连已达最大次数 |
| 2006 |
ERROR_SERIAL_NO_DEVICE |
未找到可用的 USB 串口设备 |
| 2007 |
ERROR_SERIAL_PERMISSION_DENIED |
USB 权限被拒绝 |
| 2008 |
ERROR_SERIAL_DTR_FAILED |
设置 DTR 失败 |
| 2009 |
ERROR_SERIAL_RTS_FAILED |
设置 RTS 失败 |
注意事项
- 页面卸载(onUnload/onHide)必须调用
client.destroy(),或将实例交给 hardwareManager 统一管理并在卸载时调用 destroyAll(),否则线程泄漏、后台持续连接
- 对接自定义硬件协议时,优先使用
packet 运行时配置(帧头/长度域/CRC),无需修改插件源码
- USB 串口需要 Android USB Host 支持,且需用户授权(调用
requestPermission())
- iOS 串口与 Modbus RTU 不支持(无 USB Host 能力),构造即抛错;iOS 的 TCP/Modbus TCP 原生实现需在 Mac 环境编译验证
- 模拟器网络行为与真机有差异,建议使用真实 Android 工控平板/PDA 调试
- 原生层发送(含心跳)统一经单线程写执行器串行化,确保不会因并发写导致报文字节交错
hex2buf() 输入为奇数长度或含非十六进制字符时会抛异常,请确保入参合法
- Android WebSocket 基于 okhttp(config.json 已声明三方依赖),本地真机运行需在 HBuilderX 配置离线运行环境(含 mavenCentral 依赖缓存),或提交云端打自定义基座
- Modbus 未连接时发起请求会立即 reject(
MODBUS_LOCAL_ERR_DISCONNECTED);串行模式下(serialRequests: true 或 RTU)前一个请求失败/超时不会阻塞后续请求
- 对响应数据长度的强校验(byteCount 异常返回
MODBUS_LOCAL_ERR_RESPONSE)可提前发现非 Modbus 设备串扰或错误分帧
开发计划
- [x] TCP 长连接基座
- [x] 指数退避重连
- [x] 心跳保活 + 超时检测 + 读超时检测(1006)
- [x] 可配置粘包分包处理器(含 CRC16 校验与长度上限防卡死)
- [x] Modbus TCP 协议封装(含参数边界校验)
- [x] Modbus RTU(Android)
- [x] USB 转串口(流控 + DTR/RTS 控制 + 热插拔监听)
- [x] TLS/SSL 加密传输
- [x] 多回调监听、状态主动查询、统一错误码、sendAsync
- [x] 寄存器转换工具
- [x] 多连接管理器
- [x] iOS 平台支持(TCP / Modbus TCP)
- [x] WebSocket 支持(Android / iOS)
- [x] Modbus 大段自动分片(count>125)+ 不连续地址批量读取
- [x] Modbus 请求串行队列(TCP
serialRequests)、动态 setUnitId、未连接立即报错
- [x] Modbus 响应 byteCount 强校验(-6)、位越界保护
- [x] 64 位寄存器转换(int64/uint64/float64)
License
Apache-2.0