更新记录
1.0.0(2025-08-30)
发布初始版本(1.0.0) 1、支持串口号、波特率、停止位、数据位、校验位、流控等参数设置。 2、支持多串口同时打开,进行数据收发。
平台兼容性
uni-app(4.07)
Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
---|---|---|---|---|---|---|---|---|
√ | √ | - | - | √ | √ | 4.4 | - | - |
微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
---|---|---|---|---|---|---|---|---|---|---|
- | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.07)
Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
---|---|---|---|---|---|
- | - | 5.0 | - | - | - |
方法列表:
1、获取串口列表:
/**
* 获取串口列表
* @return 串口列表
*/
getAllDevices() : Array<string>
一、单串口:
2、打开通用串口:
/**
* 打开单个串口
* @param portStr 串口设备 路径 必须参数
* @param ibaudRate 波特率 必须参数
* @param mStopBits 停止位 可选参数 默认1
* @param mDataBits 数据位 可选参数 默认8
* @param mParity 校验位 可选参数 默认0
* @param mFlowCon 标志 可选参数 默认0
* @return 是否打开成功
* 0:打开串口成功
* -1:无法打开串口:没有串口读/写权限!
* -2:无法打开串口:未知错误!
* -3:无法打开串口:参数错误!
*/
openSerialPort(portStr : string, ibaudRate : number, mStopBits : number = 1, mDataBits : number = 8, mParity : number = 0, mFlowCon : number = 0) : number
3、发送串口数据(hex数据)
/**
* 适用于通用单个串口打开的方式发送数据
* 注意发送的数据类型为hex
* @param hexData 发送的数据
*/
sendHexData(hexData : string)
4、发送串口数据(文本字符串数据)
/**
* 适用于通用单个串口打开的方式发送数据
* 注意发送的数据类型为字符串
* @param txtData 发送的数据
*/
sendTxtData(txtData : string)
5、发送串口数据(字节数组数据)
/**
* 适用于通用单个串口打开的方式发送数据
* 注意发送的数据类型为字节数组
* @param byteArrayData 发送的数据
*/
sendByteArrayData(byteArrayData : Array<number>)
6、串口回调监听
/**
* 适用于单一通用串口打开的方式回调监听
* OnNormalDataListener 为串口的接收数据回调,建议在当前类去实现这个接口
* 不用时记得释放
*/
getReceiveDataNormal(callback : (hexData : string | null) => void) : void
7、关闭串口
/**
* 关闭串口
* 适用于通过openSerialPort打开的串口关闭
*/
closeSerialPort()
8、查看串口是否打开
/**
* 查看串口是否打开
* 通过openSerialPort打开的串口状态
* @return boolean
*/
isOpenNormal() : boolean
9、移除数据返回监听器
/**
* 移除通过 openSerialPort 打开的数据监听器。
* 建议在不再需要接收数据时调用此方法,以避免内存泄漏和不必要的资源占用。
*/
removeNormalDataListener()
一、多串口:
10、打开多串口
/**
* 打开多个串口
* 此方法可多次调用,添加多个串口
* @param portStr 串口设备 路径 必须参数
* @param ibaudRate 波特率 必须参数
* @param mStopBits 停止位 可选参数 默认1
* @param mDataBits 数据位 可选参数 默认8
* @param mParity 校验位 可选参数 默认0
* @param mFlowCon 标志 可选参数 默认0
* @return 是否打开成功
* 0:打开串口成功
* -1:无法打开串口:没有串口读/写权限!
* -2:无法打开串口:未知错误!
* -3:无法打开串口:参数错误!
*/
openSerialPortCom(portStr : string, ibaudRate : number, mStopBits : number = 1, mDataBits : number = 8, mParity : number = 0, mFlowCon : number = 0) : number
注意:同时使用多串口时,使用该方法打开串口,可多次调用,传入不同的串口号。
11、多串口情况下的数据发送(hex数据)
/**
* 适用于多串口打开的方式发送数据
* 注意发送的数据类型为hex
* @param portStr 串口号(即需要往哪个串口发送数据)
* @param hexData 发送的数据
*/
sendHexDataCom(portStr : string, hexData : string)
12、多串口情况下的数据发送(文本字符串数据)
/**
* 适用于多串口打开的方式发送数据
* 注意发送的数据类型为字符串
* @param portStr 串口号(即需要往哪个串口发送数据)
* @param txtData 发送的数据
*/
sendTxtDataCom(portStr : string, txtData : string)
13、多串口情况下的数据发送(字节数组数据)
/**
* 适用于多串口打开的方式发送数据
* 注意发送的数据类型为字节数组
* @param portStr 串口号(即需要往哪个串口发送数据)
* @param byteArrayData 发送的数据
*/
sendByteArrayDataCom(portStr : string, byteArrayData : Array<number>)
14、多串口情况下的串口回调监听
/**
* 适用于多串口打开的方式回调监听
* OnComDataListener 为串口的接收数据回调
* 不用时记得释放
*/
getReceiveDataCom(callback : (com : string | null, hexData : string | null) => void) : void
15、多串口情况下的串口关闭
/**
* 关闭串口
* @param portStr 串口号
* 适用于通过openSerialPortCom打开的串口关闭
*/
closeSerialPortCom(portStr : string)
16、多串口情况下的串口查看串口是否打开
/**
* 查看串口是否打开
* 通过 openSerialPortCom 打开的串口状态
* @param portStr 串口号
* @return boolean
*/
isOpenCom(portStr : string) : boolean
17、多串口情况下的移除数据返回监听器
/**
* 移除通过 openSerialPortCom 打开的数据监听器。
* 建议在不再需要接收数据时调用此方法,以避免内存泄漏和不必要的资源占用。
*/
removeComDataListener()
用法举例:
注意:别忘记使用自定义基座运行。
下方为简易使用方法,可供参考:
<template>
<view class="container">
<text class="status-text">串口状态: {{ serialPortStatus }}</text>
<text class="received-data-text">接收数据: {{ receivedData }}</text>
<button @click="openPort" :disabled="isPortOpen">打开串口</button>
<button @click="closePort" :disabled="!isPortOpen">关闭串口</button>
<button @click="sendTestData" :disabled="!isPortOpen">发送测试数据 (Hex)</button>
<button @click="sendTestTxtData" :disabled="!isPortOpen">发送测试数据 (Txt)</button>
<button @click="sendTestByteArrayData" :disabled="!isPortOpen">发送测试数据 (ByteArray)</button>
<button @click="getAllDevicesMethod">获取设备列表</button>
<text class="device-info">当前设备: {{ currentDevicePath }}</text>
<text class="device-info">波特率: {{ baudRate }}</text>
<button @click="openMultiPort1">打开多串口1 (COM1)</button>
<button @click="openMultiPort2">打开多串口2 (COM2)</button>
<button @click="sendMultiPort1Data" :disabled="!isMultiPort1Open">发送数据到COM1</button>
<button @click="sendMultiPort2Data" :disabled="!isMultiPort2Open">发送数据到COM2</button>
<button @click="sendTestByteArrayDataCom" :disabled="!isMultiPort1Open">发送测试数据到COM1 (ByteArray)</button>
<button @click="closeAllMultiPorts">关闭所有多串口</button>
<text class="log-area">日志:</text>
<textarea class="log-output" v-model="logOutput" readonly></textarea>
</view>
</template>
<script>
import { getAllDevices, openSerialPort, sendHexData, sendTxtData, sendByteArrayData, getReceiveDataNormal, openSerialPortCom, sendHexDataCom, sendTxtDataCom, sendByteArrayDataCom, getReceiveDataCom, closeSerialPort, closeSerialPortCom, isOpenNormal, isOpenCom, removeNormalDataListener, removeComDataListener } from '../../uni_modules/shutao-serialport'
export default {
data() {
return {
serialPortStatus: false,
receivedData: '',
isPortOpen: false,
currentDevicePath: '', // 示例:你可以根据getAllDevices获取到后设置
baudRate: 9600,
logOutput: '',
// 多串口相关状态
isMultiPort1Open: false,
isMultiPort2Open: false,
multiPort1Path: '/dev/ttyS0', // 示例路径,根据你的设备修改
multiPort2Path: '/dev/ttyS1', // 示例路径,根据你的设备修改
}
},
created() {
this.checkSinglePortStatus();
this.checkMultiPortStatus();
this.setupNormalDataListener();
this.setupComDataListener();
},
beforeDestroy() {
// 在组件销毁前移除监听器,防止内存泄漏
removeNormalDataListener();
removeComDataListener();
},
methods: {
log(message : string) {
const timestamp = new Date().toLocaleTimeString();
this.logOutput += `[${timestamp}] ${message}\n`;
// 保持滚动条在底部
this.$nextTick(() => {
const textarea = this.$el?.querySelector('.log-output');
if (textarea != null) {
textarea.scrollTop = textarea.scrollHeight;
}
});
},
// ======================================
// 单串口方法测试
// ======================================
async getAllDevicesMethod() {
this.log('正在获取所有串口设备...');
try {
const devices = getAllDevices();
if (devices.length > 0) {
this.log('获取到串口设备: ' + devices.join(', '));
// 示例:自动选择第一个设备作为当前设备
this.currentDevicePath = devices[0];
} else {
this.log('未找到任何串口设备。');
this.currentDevicePath = '';
}
} catch (e) {
this.log('获取设备列表失败: ' + e.message);
}
},
async openPort() {
if (this.currentDevicePath == '') {
this.log('请先获取设备列表并选择一个设备。');
return;
}
this.log(`正在打开串口: ${this.currentDevicePath} (波特率: ${this.baudRate})...`);
try {
const result = openSerialPort(this.currentDevicePath, this.baudRate);
if (result === 0) {
this.serialPortStatus = true;
this.isPortOpen = true;
this.log('串口打开成功!');
// 确保监听器已设置
this.setupNormalDataListener();
} else {
let errorMessage = '未知错误';
if (result === -1) errorMessage = '没有串口读/写权限';
if (result === -2) errorMessage = '未知错误';
if (result === -3) errorMessage = '参数错误';
this.log(`串口打开失败: ${errorMessage} (代码: ${result})`);
this.serialPortStatus = false;
}
} catch (e) {
this.log('打开串口时发生异常: ' + e.message);
this.serialPortStatus = false;
}
},
async closePort() {
this.log('正在关闭串口...');
try {
closeSerialPort();
this.serialPortStatus = false;
this.isPortOpen = false;
this.receivedData = '';
this.log('串口关闭成功!');
// 移除监听器
removeNormalDataListener();
} catch (e) {
this.log('关闭串口时发生异常: ' + e.message);
}
},
async sendTestData() {
if (!this.isPortOpen) {
this.log('串口未打开,无法发送数据。');
return;
}
const hexData = '0102030405'; // 示例HEX数据
this.log('正在发送HEX数据: ' + hexData);
try {
sendHexData(hexData);
this.log('HEX数据发送成功。');
} catch (e) {
this.log('发送HEX数据失败: ' + e.message);
}
},
async sendTestTxtData() {
if (!this.isPortOpen) {
this.log('串口未打开,无法发送数据。');
return;
}
const txtData = 'Hello UniAppX!'; // 示例字符串数据
this.log('正在发送TXT数据: ' + txtData);
try {
sendTxtData(txtData);
this.log('TXT数据发送成功。');
} catch (e) {
this.log('发送TXT数据失败: ' + e.message);
}
},
async sendTestByteArrayData() {
if (!this.isPortOpen) {
this.log('串口未打开,无法发送数据。');
return;
}
// 示例字节数组 (对应 [1, 2, 3, 4, 5])
// 在 UTS 中,ByteArray 可以直接用 number[] 来表示
const byteArrayRaw = [0x01, 0x02, 0x03, 0x04, 0x05];
// 创建一个 Uint8Array
this.log('正在发送ByteArray数据: ' + byteArrayRaw.map(byte => byte.toString(16).padStart(2, '0')).join(' '));
try {
sendByteArrayData(byteArrayRaw);
this.log('ByteArray数据发送成功。');
} catch (e) {
this.log('发送ByteArray数据失败: ' + e.message);
}
},
checkSinglePortStatus() {
try {
this.serialPortStatus = isOpenNormal();
this.log(`单串口初始状态: ${this.serialPortStatus}`);
} catch (e) {
this.log('检查单串口状态失败: ' + e.message);
}
},
setupNormalDataListener() {
this.log('设置单串口数据监听...');
try {
getReceiveDataNormal((hexData) => {
if (hexData?.length == 0) {
this.receivedData = hexData;
this.log(`收到单串口数据 (Hex): ${hexData}`);
} else {
this.log('收到单串口空数据。');
}
});
this.log('单串口数据监听器已设置。');
} catch (e) {
this.log('设置单串口数据监听失败: ' + e.message);
}
},
// ======================================
// 多串口方法测试
// ======================================
async openMultiPort1() {
this.log(`正在打开多串口1: ${this.multiPort1Path} (波特率: ${this.baudRate})...`);
try {
const result = openSerialPortCom(this.multiPort1Path, this.baudRate);
if (result === 0) {
this.isMultiPort1Open = true;
this.log(`多串口1 (${this.multiPort1Path}) 打开成功!`);
this.setupComDataListener(); // 确保监听器已设置
} else {
let errorMessage = '未知错误';
if (result === -1) errorMessage = '没有串口读/写权限';
if (result === -2) errorMessage = '未知错误';
if (result === -3) errorMessage = '参数错误';
this.log(`多串口1 (${this.multiPort1Path}) 打开失败: ${errorMessage} (代码: ${result})`);
}
} catch (e) {
this.log('打开多串口1时发生异常: ' + e.message);
}
},
async openMultiPort2() {
this.log(`正在打开多串口2: ${this.multiPort2Path} (波特率: ${this.baudRate})...`);
try {
const result = openSerialPortCom(this.multiPort2Path, this.baudRate);
if (result === 0) {
this.isMultiPort2Open = true;
this.log(`多串口2 (${this.multiPort2Path}) 打开成功!`);
this.setupComDataListener(); // 确保监听器已设置
} else {
let errorMessage = '未知错误';
if (result === -1) errorMessage = '没有串口读/写权限';
if (result === -2) errorMessage = '未知错误';
if (result === -3) errorMessage = '参数错误';
this.log(`多串口2 (${this.multiPort2Path}) 打开失败: ${errorMessage} (代码: ${result})`);
}
} catch (e) {
this.log('打开多串口2时发生异常: ' + e.message);
}
},
async sendMultiPort1Data() {
if (!this.isMultiPort1Open) {
this.log('多串口1未打开,无法发送数据。');
return;
}
const hexData = '0A0B0C'; // 示例HEX数据
this.log(`正在向多串口1 (${this.multiPort1Path}) 发送HEX数据: ${hexData}`);
try {
sendHexDataCom(this.multiPort1Path, hexData);
this.log('多串口1 HEX数据发送成功。');
} catch (e) {
this.log('向多串口1发送HEX数据失败: ' + e.message);
}
},
async sendMultiPort2Data() {
if (!this.isMultiPort2Open) {
this.log('多串口2未打开,无法发送数据。');
return;
}
const txtData = 'Data for COM2'; // 示例字符串数据
this.log(`正在向多串口2 (${this.multiPort2Path}) 发送TXT数据: ${txtData}`);
try {
sendTxtDataCom(this.multiPort2Path, txtData);
this.log('多串口2 TXT数据发送成功。');
} catch (e) {
this.log('向多串口2发送TXT数据失败: ' + e.message);
}
},
async sendTestByteArrayDataCom() {
if (!this.isPortOpen) {
this.log('串口未打开,无法发送数据。');
return;
}
// 示例字节数组 (对应 [1, 2, 3, 4, 5])
// 在 UTS 中,ByteArray 可以直接用 number[] 来表示
const byteArrayRaw = [0x01, 0x02, 0x03, 0x04, 0x05];
// 创建一个 Uint8Array
this.log('正在发送ByteArray数据: ' + byteArrayRaw.map(byte => byte.toString(16).padStart(2, '0')).join(' '));
try {
sendByteArrayDataCom(this.multiPort1Path, byteArrayRaw);
this.log('ByteArray数据发送成功。');
} catch (e) {
this.log('发送ByteArray数据失败: ' + e.message);
}
},
async closeAllMultiPorts() {
this.log('正在关闭所有多串口...');
try {
// 注意:closeSerialPortCom 方法没有参数,会关闭所有已通过 openSerialPortCom 打开的串口。
closeSerialPortCom(this.multiPort1Path);
closeSerialPortCom(this.multiPort2Path);
this.isMultiPort1Open = false;
this.isMultiPort2Open = false;
this.log('所有多串口已关闭。');
// 移除监听器
removeComDataListener();
} catch (e) {
this.log('关闭所有多串口时发生异常: ' + e.message);
}
},
checkMultiPortStatus() {
try {
// 注意:isOpenCom 需要传入串口路径来检查单个多串口的状态
this.isMultiPort1Open = isOpenCom(this.multiPort1Path);
this.isMultiPort2Open = isOpenCom(this.multiPort2Path);
this.log(`多串口1 (${this.multiPort1Path}) 初始状态: ${this.isMultiPort1Open ? '已打开' : '已关闭'}`);
this.log(`多串口2 (${this.multiPort2Path}) 初始状态: ${this.isMultiPort2Open ? '已打开' : '已关闭'}`);
} catch (e) {
this.log('检查多串口状态失败: ' + e.message);
}
},
setupComDataListener() {
this.log('设置多串口数据监听...');
try {
getReceiveDataCom((com, hexData) => {
if (com != '' && hexData != '') {
this.log(`收到多串口数据 (${com}, Hex): ${hexData}`);
// 你可以根据com来更新不同的UI显示,这里只是简单记录日志
} else {
this.log(`收到多串口空数据或无效数据 (com: ${com}, hexData: ${hexData})。`);
}
});
this.log('多串口数据监听器已设置。');
} catch (e) {
this.log('设置多串口数据监听失败: ' + e.message);
}
}
}
}
</script>
<style>
.container {
display: flex;
flex-direction: column;
padding: 20rpx;
}
.status-text,
.received-data-text,
.device-info,
.log-area {
margin-bottom: 10rpx;
font-size: 30rpx;
}
button {
margin-bottom: 20rpx;
width: 100%;
height: 80rpx;
line-height: 80rpx;
font-size: 32rpx;
}
.log-output {
width: 100%;
height: 400rpx;
border: 1px solid #eee;
padding: 10rpx;
font-size: 26rpx;
background-color: #f9f9f9;
box-sizing: border-box;
}
</style>