HarmonyOS鸿蒙Next中开发应用怎么对接usb串口
HarmonyOS鸿蒙Next中开发应用怎么对接usb串口 使用的SDK 是5.0.5(17)版本的,目前文档上虽然有串口通信 但是我这版本不支持,且大部分的手机都是鸿蒙5.0以下的版本,在应用中需要用到串口通信的一个功能 1 当前应用中暂时使用的是
import { usbManager } from '@kit.BasicServicesKit';
通过这个usb管理来获取链接设备,并进行通信,前提是 手机需要安装一个串口联调应用先进行波特率数据的配置才能在 自己开发的应用上面使用,且当usb断开连接后 在应用中也进行了关闭通道处理,但是在次插入usb连接时进行发送编码通信就不行了 usb通道就没有响应数据了导致应用阻塞并且重启,然后usb通道就一直不通了 需要关机重启 重新配置才能再次使用,哪位大佬指点一下 usb代码如下
import { usbManager } from '@kit.BasicServicesKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { buffer } from '@kit.ArkTS';
import hilog from '@ohos.hilog';
const TAG: string = 'SerialPort';
export class USBCommunication {
private usbDevice: usbManager.USBDevice | null = null;
private devicePipe: usbManager.USBDevicePipe | null = null;
private usbInterface: usbManager.USBInterface | undefined;
private usbEndpoint: usbManager.USBEndpoint | undefined;
private readEndpoint: usbManager.USBEndpoint | undefined;
private mIsReadFree: boolean = true; // 读通道是否空闲
private mIsWriteFree: boolean = true; // 写通道是否空闲
constructor() {}
public async initialize() {
// 获取当前链接设备
if(!this.usbDevice){
this.usbDevice = this.getUSBDevice();
}else{
this.close()
}
if (this.usbDevice) {
// 如果有设备的情况下判断是否有权限
console.log(JSON.stringify(this.usbDevice))
const hasPermission = await this.checkUSBPermission(this.usbDevice);
console.log(hasPermission+'设备权限')
if (hasPermission) {
// 有设备权限的情况下获取设备列表中的参数,用来做数据的传输
this.setupUSBInterface(this.usbDevice);
}
}
}
private getUSBDevice(): usbManager.USBDevice | null {
const deviceList: Array<usbManager.USBDevice> = usbManager.getDevices();
console.info(`Device List: ${JSON.stringify(deviceList)}`);
if (deviceList.length === 0) {
hilog.error(0x0002, TAG, "Device list is empty");
return null;
}
return deviceList[0];
}
private async checkUSBPermission(us: usbManager.USBDevice): Promise<boolean> {
const deviceName: string = us.name;
console.log(deviceName+1)
try {
const hasRight: boolean = await usbManager.requestRight(deviceName);
hilog.info(0x0002, TAG, hasRight ? "Permission granted" : "Permission denied");
return hasRight;
} catch (error) {
console.error(`USB device request right failed: ${error}`);
return false;
}
}
// 移除权限
private async removeRight(us: usbManager.USBDevice): Promise<boolean> {
const deviceName: string = us.name;
console.log(deviceName+2)
try {
const removeRightData: boolean = await usbManager.removeRight(deviceName);
console.log('权限移除');
return removeRightData;
} catch (error) {
console.error(`USB device request right failed: ${error}`);
return false;
}
}
private setupUSBInterface(usbDevice: usbManager.USBDevice) {
console.log('Setting up USB interface');
// 获取设备中的数据传输通道
const res= this.getUsbInterface(usbDevice);
if (res[0] &&res[1]) {
this.usbInterface = res[0];
this.usbEndpoint = res[1];
this.readEndpoint = res[2];
// 打开设备,获取数据传输通道。
this.devicePipe = this.registerInterface(usbDevice, this.usbInterface, this.usbEndpoint );
}
}
private getUsbInterface(usbDevice: usbManager.USBDevice): [usbManager.USBInterface | undefined, usbManager.USBEndpoint | undefined, usbManager.USBEndpoint | undefined] {
let usbConfigs: usbManager.USBConfiguration[] = usbDevice.configs;
let usbInterface: usbManager.USBInterface | undefined;
let usbEndpoint: usbManager.USBEndpoint | undefined;
let readEndpoint: usbManager.USBEndpoint | undefined;
for (const config of usbConfigs) {
for (const iface of config.interfaces) {
usbEndpoint = iface.endpoints.find(value => value.direction === 0 && value.type === 2);
readEndpoint = iface.endpoints.find(value => value.direction === 128 && value.type === 2);
if (usbEndpoint) {
usbInterface = iface;
break;
}
}
if (usbInterface) break;
}
if (!usbEndpoint) {
console.error(`USB endpoint not found`);
}
return [usbInterface, usbEndpoint, readEndpoint];
}
private registerInterface(usbDevice: usbManager.USBDevice, usbInterface: usbManager.USBInterface, usbEndpoint: usbManager.USBEndpoint) {
this.devicePipe = usbManager.connectDevice(usbDevice);
// 声明对USB设备某个接口的控制权。
const claimInterfaceResult: number = usbManager.claimInterface(this.devicePipe, usbInterface, true);
console.log(claimInterfaceResult + ' Interface claimed successfully');
if (claimInterfaceResult !== 0) {
console.error(`Claim interface error = ${claimInterfaceResult}`);
return null;
}
// 如果通道是实时的情况下重新设置控制
if (usbEndpoint.type === 1) {
const setInterfaceResult = usbManager.setInterface(this.devicePipe, usbInterface);
if (setInterfaceResult !== 0) {
console.error(`Set interface error = ${setInterfaceResult}`);
return null;
}
}
return this.devicePipe;
}
// 进行设备通信的数据发送
public async sendData(data: string) {
if (!this.devicePipe || !this.usbEndpoint) {
console.error("Device pipe or USB endpoint is not initialized");
return;
}
console.log('Sending data: ' + data);
// 使用将十六进制中去除0x前缀
const cleanHex = this.sanitizeHex(data);
if (!cleanHex || cleanHex.length % 2 !== 0) return;
try {
const dataLength = await usbManager.bulkTransfer(this.devicePipe, this.usbEndpoint, new Uint8Array(buffer.from(cleanHex, 'hex').buffer), 15000);
if (dataLength >= 0) {
console.info(`USB write data result: write length = ${dataLength}`);
usbManager.releaseInterface(this.devicePipe!, this.usbInterface!);
} else {
this.close()
console.error("USB write data failed");
}
} catch (error) {
this.close()
console.error(`USB write data error: ${error}`);
}
}
// 进行读取设备数值
public receiveData(): Promise<string> {
return new Promise((resolve, reject) => {
if (!this.devicePipe || !this.readEndpoint) {
console.error("Device pipe or read endpoint is not initialized");
reject(new Error("Device pipe or read endpoint is not initialized"));
return;
}
if (!this.mIsReadFree) {
console.error("通道被占用");
reject(new Error("Channel is busy"));
return;
}
this.mIsReadFree = false
const dataUint8Array: Uint8Array = new Uint8Array(1024);
usbManager.bulkTransfer(this.devicePipe, this.readEndpoint, dataUint8Array, 15000)
.then((dataLength: number) => {
usbManager.releaseInterface(this.devicePipe!, this.usbInterface!);
this.mIsReadFree = true
if (dataLength >= 0) {
const validData = dataUint8Array.subarray(0, dataLength);
const hexString = Array.from(validData, byte => byte.toString(16).padStart(2, '0')).join('');
// console.info(`Hex data: 0x${hexString}`);
const byteBuffer = buffer.from(hexString, 'hex');
// const resultString = byteBuffer.toString('utf-8');
const resultString = byteBuffer.toString('ascii');
// console.log(`Final result: ${resultString}`);
resolve(resultString); // 返回读取到的字符串
} else {
console.error("USB read data failed");
this.close()
reject(new Error("USB read data failed"));
}
})
.catch((error: BusinessError) => {
console.error(`USB read data error: ${error}`);
this.close()
this.mIsReadFree = true
reject(error); // 拒绝 Promise
});
});
}
public close() {
if (this.devicePipe) {
usbManager.releaseInterface(this.devicePipe!, this.usbInterface!);
usbManager.closePipe(this.devicePipe);
this.devicePipe = null
console.info("Device pipe closed");
}
}
// 移除权限并关闭设备和释放通信接口
public async removeReset(){
console.log(JSON.stringify(this.usbDevice)+'222')
if(this.usbDevice){
let removeRes = await this.removeRight(this.usbDevice)
console.log('移除权限'+removeRes)
if(removeRes){
this.close()
}
}
}
private sanitizeHex(hexInput: string): string {
return hexInput.replace(/^0x/i, '').replace(/[^0-9a-fA-F]/g, '');
}
}
在应用中的使用代码如下
@Monitor('assist.isLink') // 监听所有子属性
async onIsLinkChange(mon: IMonitor) {
console.log('设备链接'+this.assist.isLink)
if(this.usbTimeId){
clearInterval(this.usbTimeId)
this.usbTimeId = null
}
if(this.assist.isLink){
this.executeCommands()
}else{
// 当断开连接时需要关闭和清除设备链接通道和断开通信
this.USBCommunication.removeReset()
}
// mon.dirty.forEach(path => console.log(`路径 ${path} 变化`));
}
async executeCommands() {
try {
// 清空直接解析量和粉碎解析量
this.assist.directList =[]
this.assist.smashList =[]
// 发送第一个指令
await this.USBCommunication.initialize(); // 初始化 USB 通信
this.USBCommunication.sendData('0x9d');
console.log('指令 0x9d 发送成功。');
// 等待第一个指令的响应
let res = await this.USBCommunication.receiveData();
console.log(`指令 0x9d 的响应: ${res}`);
// 发送第二个指令
await this.USBCommunication.initialize(); // 初始化 USB 通信
this.USBCommunication.sendData('0x56');
console.log('指令 0x56 发送成功。');
// 等待第二个指令的响应
let res2 = await this.USBCommunication.receiveData();
console.log(`指令 0x56 的响应: ${res2}`);
// 在发送两个指令并接收到响应后,开始定时器
this.usbTimeId = setInterval(async () => {
try {
await this.USBCommunication.initialize(); // 初始化 USB 通信
const response = await this.USBCommunication.receiveData();
const numberString = response.split('=')[1]?.trim()
// 转换为数值 除以1000 得到每分钟ml的数值
const value = Number((numberString ? parseFloat(numberString) : 0)) / 1000; // 使用 parseFloat 转换为浮点数
console.log(`定时响应: ${value}`);
// 直接测定开始时将获取的数据存储在存储到数组中
if(this.measureModel==1){
this.assist.directList.push(value)
}
// 粉碎测定开始时将获取的数据存储在存储到数组中
if(this.measureModel==2){
this.assist.smashList.push(value)
}
// 当开始读取usb设备数据时 就可以点击测定开始按钮
this.assist.directBtn = true
} catch (error) {
if(this.usbTimeId){
clearInterval(this.usbTimeId)
this.usbTimeId = null
}
console.error(`接收数据时出错: ${error}`);
}
}, 200);
} catch (error) {
console.error(`执行指令时出错: ${error}`);
if(this.usbTimeId){
clearInterval(this.usbTimeId)
this.usbTimeId = null
}
} finally {
// 可选:在某个时刻关闭通信
// usbComm.close(); // 如果希望立即关闭,可以取消注释
}
}
更多关于HarmonyOS鸿蒙Next中开发应用怎么对接usb串口的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中对接USB串口,需使用@ohos.usbV9接口。首先在module.json5中声明USB设备使用权限和设备过滤信息。通过usb.getDevices()获取设备列表,使用usb.openDevice()打开指定设备。获取设备接口后,使用usb.claimInterface()声明接口。通过usb.bulkTransfer()进行批量数据传输,或使用usb.controlTransfer()进行控制传输。使用完毕后,调用usb.releaseInterface()和usb.closeDevice()释放资源。
更多关于HarmonyOS鸿蒙Next中开发应用怎么对接usb串口的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
根据你的代码分析,主要问题在于USB接口和管道的管理逻辑。在sendData和receiveData方法中,每次传输后都调用了releaseInterface,这会释放对接口的占用。但在下一次传输时,代码没有重新claimInterface,导致后续操作失败。
问题核心在sendData方法:
if (dataLength >= 0) {
console.info(`USB write data result: write length = ${dataLength}`);
usbManager.releaseInterface(this.devicePipe!, this.usbInterface!); // 这里释放了接口
}
同样在receiveData的Promise回调中也有:
usbManager.releaseInterface(this.devicePipe!, this.usbInterface!);
修改建议:
- 移除
sendData和receiveData中的releaseInterface调用 - 只在真正需要关闭连接时(如设备断开、应用退出)调用
releaseInterface - 确保每次
initialize时,如果已有devicePipe,先正确关闭再重新初始化
在initialize方法中,当usbDevice已存在时调用close()是正确做法,但需要确保close方法完全释放资源。
另外,在应用代码中频繁调用initialize()也可能导致问题。建议在连接建立后保持USB状态,而不是每次发送/接收都重新初始化。

