更新记录

1.0.0(2026-10-30)

  • 首次发布:安卓 USB 转串口通信插件,支持 uni-app 与 uni-app x
  • 串口枚举、打开(自动申请 USB 授权)、关闭
  • 波特率 / 数据位 / 停止位 / 校验位 / 流控设置与运行时修改
  • 文本与 Base64 二进制读写、后台持续接收
  • DTR / RTS 电平控制、控制线状态读取、硬件收发缓冲区清空
  • USB 插拔监听,设备拔出时自动关闭串口
  • 资源释放接口,支持页面卸载时一次性回收

平台兼容性

uni-app(4.72)

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

uni-app x(4.72)

Chrome Safari Android Android插件版本 iOS 鸿蒙 微信小程序
× × 5.0 1.0.0 × × ×

插件介绍

安卓 USB 转串口(OTG)UTS 原生插件。手机通过 USB Host 直接与 USB 转串口模块通信,无需 root、无需访问 /dev/tty* 节点。

支持 uni-app 与 uni-app x, 无需额外集成任何库。

支持的芯片

芯片 / 设备 driverName VID PID 端口数
CH340 Ch34xSerialDriver 0x1A86 0x7523 1
CH341A Ch34xSerialDriver 0x1A86 0x5523 1
CP2101 / CP2102 / CP2103 / CP2104 / CP2109 Cp21xxSerialDriver 0x10C4 0xEA60 按接口数(通常 1)
CP2105 Cp21xxSerialDriver 0x10C4 0xEA70 2
CP2108 Cp21xxSerialDriver 0x10C4 0xEA71 4
FT232R FtdiSerialDriver 0x0403 0x6001 1
FT232H FtdiSerialDriver 0x0403 0x6014 1
FT230X / FT231X / FT234XD FtdiSerialDriver 0x0403 0x6015 1
FT2232H FtdiSerialDriver 0x0403 0x6010 2
FT4232H FtdiSerialDriver 0x0403 0x6011 4
PL2303(type 01 / T / HX) ProlificSerialDriver 0x067B 0x2303 1
PL2303GC / GB / GT / GL / GE / GS ProlificSerialDriver 0x067B 0x23A3 / 0x23B3 / 0x23C3 / 0x23D3 / 0x23E3 / 0x23F3 1
CDC-ACM 标准串口(Arduino Uno / Mega、树莓派 Pico、STM32 VCP、ESP32-S3 原生 USB 等) CdcAcmSerialDriver 按 USB CDC 接口描述符自动识别,不依赖 VID/PID — 按数据接口数
Fibocom L610 / L612(4G 模组 AT 串口) GsmModemSerialDriver 0x1782 0x4D10 / 0x4D12 1
Google CR50(Chromebook 调试串口) ChromeCcdSerialDriver 0x18D1 0x5014 1

说明:

  • 表中 driverName 即 getDeviceList 返回的 ports[i].driverName,可据此在业务里区分芯片型号。
  • 插件返回的 vendorId / productId 是十进制,例如 CH340 为 6790 / 29987(即 0x1A86 / 0x7523)。
  • 多端口芯片(CP2105 / CP2108 / FT2232H / FT4232H 等)在 getDeviceList 中会按「设备 × 端口」展开成多条记录,用各自的 index 分别打开。
  • CDC-ACM 靠接口描述符识别而非 VID/PID,因此大量自研 USB 虚拟串口设备(含复合设备)也能直接识别。
  • 不在表中的芯片不会被枚举出来,getDeviceList 只会返回能匹配到驱动的设备。

使用场景

  • 工控 / 医疗 / 检测设备通过 USB 转串口模块(RS232 / RS485 转 USB)读取传感器与仪器数据
  • 小票打印机、电子秤、扫码模块等串口外设与 App 通信
  • 现场调试时用手机替代电脑串口助手,收发 AT 指令或自定义协议帧

使用流程

  1. 注册监听:registerUsbStateReceiver({ onEvent }) 监听插拔,拔出时插件会自动关闭当前串口。
  2. 枚举串口:getDeviceList({ success }) 拿到可用串口列表,ports[i].index 即后续打开用的下标。
  3. 打开串口:openPort({ index, baudRate, ... }),设备未授权时自动弹出系统 USB 授权框,用户允许后自动继续打开。
  4. 收发数据:write({ data }) 发送,startReadLoop({ onData }) 持续接收,或 read({ timeout }) 单次读取。
  5. 关闭与释放:stopReadLoop() → closePort() → releaseResources()(页面 onUnload 调用)。

运行须知:插件内含预编译的原生串口驱动,必须打自定义基座运行(标准基座不含该依赖);手机需支持 OTG,部分机型需在系统设置中打开 OTG 开关。

用法

import {
    getDeviceList,
    openPort,
    closePort,
    read,
    write,
    setParameters,
    setControlSignals,
    getControlLines,
    clearBuffers,
    startReadLoop,
    stopReadLoop,
    registerUsbStateReceiver,
    releaseResources
} from '@/uni_modules/zy-usb-serial'

注册插拔监听

registerUsbStateReceiver({
    onEvent: (e) => {
        // e.event 取值:deviceAttached(插入) / deviceDetached(拔出,串口已被自动关闭)
        if (e.event === 'deviceAttached') {
            console.log('串口模块已插入:' + e.deviceName)
        } else {
            console.log('串口模块已拔出:' + e.deviceName)
        }
    },
    success: (res) => console.log(res.errMsg),
    fail: (err) => console.log('监听注册失败 ' + err.errCode + ' ' + err.errMsg)
})

枚举并打开串口

getDeviceList({
    success: (res) => {
        console.log('可用串口:' + res.ports.length)
        // 波特率缺省 115200,数据位 8,停止位 1,校验位 0(无),流控 0(无)
        openPort({
            index: res.ports[0].index,
            baudRate: 115200,
            readTimeout: 500, // 该串口默认读超时(毫秒,0 为一直阻塞)
            success: (info) => console.log('已打开 ' + info.driverName + ' 端口 ' + info.portIndex),
            fail: (err) => console.log('打开失败 ' + err.errCode + ' ' + err.errMsg)
        })
    },
    fail: (err) => console.log('枚举失败 ' + err.errCode + ' ' + err.errMsg)
})

发送数据

// 文本(UTF-8)
write({ data: 'AT+CSQ\r\n', success: (res) => console.log('已发送 ' + res.bytes + ' 字节') })

// 十六进制:空格、逗号、短横线、0x 前缀都会被自动忽略
write({ hex: '00 01 02 03', success: (res) => console.log(res.bytes) })
write({ hex: '0x00,0x01,0x02,0x03', success: (res) => console.log(res.bytes) })

// 二进制:传 Base64,例如 0x00 0x01 0x02 0x03 => 'AAECAw=='
write({ base64: 'AAECAw==', timeout: 2000, success: (res) => console.log(res.bytes) })

持续接收

startReadLoop({
    readTimeout: 200, // 缺省取 openPort 的 readTimeout;0 会被按 100 毫秒处理
    bufferSize: 4096,
    onData: (d) => {
        // d.bytes / d.base64 / d.hex / d.text
        console.log('收到 ' + d.bytes + ' 字节:' + d.hex)
    },
    onError: (err) => console.log('接收已停止 ' + err.errCode + ' ' + err.errMsg),
    success: (res) => console.log(res.errMsg)
})

stopReadLoop({ success: (res) => console.log(res.errMsg) })

单次读取

read({
    timeout: 500,   // 缺省取 openPort 的 readTimeout
    maxBytes: 256,  // 缺省 256,最大 4096
    success: (d) => {
        // 超时没有数据时 d.bytes 为 0(不算失败)
        console.log(d.bytes, d.hex, d.text)
    }
})

修改参数与控制线

setParameters({
    baudRate: 9600,
    success: (info) => console.log(info.baudRate + ' ' + info.dataBits + ' ' + info.parity)
})

setControlSignals({ dtr: true, rts: false, success: (lines) => console.log(lines) })
getControlLines({ success: (lines) => console.log(lines.cd, lines.cts, lines.dsr, lines.ri) })
clearBuffers({ input: true, output: true, success: (res) => console.log(res.errMsg) })

DTR / RTS 控制线说明

DTR、RTS 是两根调制解调器控制线,只用于给对端设备打电平信号,不承载业务数据,通过 setControlSignals 设置、getControlLines 回读。openPort 缺省已把两者置高(dtr: true, rts: true)。

信号 全称 方向 含义
dtr Data Terminal Ready 手机 → 设备 主机已就绪 / 在线
rts Request To Send 手机 → 设备 请求发送
cd Carrier Detect 设备 → 手机 载波检测(只读)
cts Clear To Send 设备 → 手机 清除发送(只读)
dsr Data Set Ready 设备 → 手机 数据装置就绪(只读)
ri Ring Indicator 设备 → 手机 振铃指示(只读)

常见用途:

  1. 给 MCU 自动复位 / 进下载模式:ESP8266、ESP32、Arduino 的下载电路把 DTR、RTS 接到 EN、IO0,靠两根线的电平组合拉出复位时序,烧录工具因此无需手动按复位键。
  2. 当普通 GPIO 用:未开硬件流控时,串口屏、继电器板、传感器常把 DTR / RTS 当额外控制线(如 RS485 收发方向、唤醒设备、切换工作模式)。
  3. 满足设备的「主机在线」判断:部分 4G 模组、串口打印机检测不到 DTR 置高会一直不回数据,现象是「发指令没反应」,把 DTR 打开即可。

注意事项:

  • 只有 flowControl = 0(无硬件流控)时手动设置 rts 才有意义;开启 RTS/CTS 流控后 RTS 由串口芯片自动管理,手动设置会被忽略或失败。
  • 部分芯片或驱动不支持这两根线,setControlSignals 会走 fail 回调,错误码 9220014(串口不支持该操作)。
  • cd / cts / dsr / ri 是输入方向,只能读;getControlLines 一次取回全部四路,比逐个读取节省 USB 请求。
  • setControlSignals 至少传一个字段,未传的字段保持当前电平;成功回调返回设置后的四路控制线状态。

关闭与释放

closePort({ success: (res) => console.log(res.errMsg) })
releaseResources({ success: (res) => console.log(res.errMsg) })

插件方法

方法 说明 回调
getDeviceList(options) 枚举可用串口,多端口设备按「设备 × 端口」展开 成功 ports 为串口数组
openPort(options) 打开串口,缺权限时自动弹窗并在授权后继续打开(超时 60 秒) 成功返回当前串口参数
closePort(options) 关闭当前串口并停止后台接收 成功 { errMsg }
read(options) 同步读取一次,timeout 缺省取 openPort 的 readTimeout 成功返回数据体
write(options) 发送数据,hex(十六进制)/ data(文本)/ base64(二进制)三选一,同时传时优先 hex 成功 { bytes }
setParameters(options) 运行时修改波特率 / 数据位 / 停止位 / 校验位 / 流控,只传需要改的字段 成功返回当前串口参数
setControlSignals(options) 设置 DTR / RTS 电平,至少传一个 成功返回控制线状态
getControlLines(options) 读取控制线状态 成功返回控制线状态
clearBuffers(options) 清空硬件收发缓冲区,input / output 缺省 true 成功 { errMsg }
startReadLoop(options) 启动后台持续接收,数据持续回调 onData 启动结果一次性回调
stopReadLoop(options) 停止后台持续接收 成功 { errMsg }
registerUsbStateReceiver(options) 注册 USB 插拔监听,拔出时自动关闭串口 注册结果一次性回调,事件持续回调
releaseResources(options) 停止接收、关闭串口、注销监听 成功 { errMsg }

write 的三种数据来源

字段 类型 说明 优先级
hex string 十六进制字符串,如 '00 01 FF'、'0x00,0x01'、'0001ff';空格 / 逗号 / 短横线 / 冒号 / 下划线 / 换行等分隔符与 0x 前缀自动忽略,有效位数为奇数或含非法字符时报 9220001 最高
base64 string Base64(不换行)编码的二进制,如 'AAECAw==' 中
data string 文本,按 UTF-8 编码后写入,如 'AT+CSQ\r\n' 最低

三者都为空时报 9220001;实际写入字节数在成功回调的 bytes 中返回,写超时缺省 2000 毫秒。

串口信息结构(getDeviceList 的 ports 元素)

{
    index : 0,               // 端口列表下标,openPort 时作为 index 传入
    deviceIndex : 0,         // 设备在 USB 设备列表中的下标
    portIndex : 0,           // 端口在设备内的下标
    portCount : 1,           // 设备内端口总数
    deviceId : 1002,         // 系统分配的设备 ID
    deviceName : '/dev/bus/usb/001/002',
    vendorId : 6790,         // 厂商 ID(十进制)
    productId : 29987,       // 产品 ID(十进制)
    productName : 'USB Serial',      // 可能为 null
    manufacturerName : 'wch.cn',     // 可能为 null
    serialNumber : null,             // 未授权或无序列号时为 null
    driverName : 'Ch34xSerialDriver' // 匹配到的驱动名
}

打开 / 参数结果结构(openPort、setParameters)

{
    index : 0,                    // 端口列表下标
    deviceId : 1002,
    vendorId : 6790,
    productId : 29987,
    driverName : 'Ch34xSerialDriver',
    portIndex : 0,
    baudRate : 115200,            // 波特率
    dataBits : 8,                 // 数据位:5 / 6 / 7 / 8
    stopBits : 1,                 // 停止位:1(1 位) / 3(1.5 位) / 2(2 位)
    parity : 0,                   // 校验位:0 无 / 1 奇 / 2 偶 / 3 Mark / 4 Space
    flowControl : 0               // 流控:0 无 / 1 RTS-CTS / 2 DTR-DSR / 3 XON-XOFF / 4 XON-XOFF 内联
}

数据体结构(read 成功、startReadLoop 的 onData)

{
    bytes : 12,        // 本次字节数;read 超时时为 0
    base64 : '...',    // Base64(不换行)编码
    hex : '41542b43',  // 十六进制小写、无分隔符
    text : 'AT+C'      // 按 UTF-8 解码的文本(二进制数据可能是乱码,请用 base64)
}

控制线结构(getControlLines 成功、setControlSignals 成功)

{
    cd : false,   // 载波检测
    cts : false,  // 清除发送
    dsr : false,  // 数据装置就绪
    ri : false    // 振铃指示
}

插拔事件结构(registerUsbStateReceiver 的 onEvent)

{
    event : 'deviceAttached',  // deviceAttached(插入) / deviceDetached(拔出)
    deviceId : 1002,
    deviceName : '/dev/bus/usb/001/002',
    vendorId : 6790,
    productId : 29987
}

错误码

错误码 说明
9220001 参数错误
9220002 串口未打开,请先调用 openPort
9220003 未找到可用的 USB 串口设备
9220004 USB 权限被拒绝
9220005 打开串口失败
9220006 串口读写失败
9220007 设置串口参数失败
9220008 关闭串口失败
9220009 应用上下文获取失败
9220010 等待 USB 授权超时
9220011 后台读取启动失败
9220012 USB 设备已拔出
9220013 释放资源失败
9220014 串口不支持该操作
9220015 串口设备被占用

权限说明

本插件不需要任何运行时权限。

权限 用途
android.hardware.usb.host(硬件特性,非运行时权限) 声明设备需要 USB Host 能力,用于访问 USB 转串口模块

说明:USB 设备访问通过系统授权弹窗逐设备授权,不涉及存储、定位等运行时权限;手机需支持 OTG。

隐私、权限声明

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

android.hardware.usb.host

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

串口收发的数据仅在本机与外部串口设备之间传输,不会上传至任何服务器

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

无

暂无用户评论。