e lectron-egg前段业务框架学习记录【3】usb设备接收数据

364 阅读2分钟

使用node-hid类库,实现打开指定usb设备,并回显数据的功能。

开发环境版本记录

开发环境 mac电脑
nodejs ,版本16.18.0 
electron ,版本21.4.4 
electron-builder ,版本23.6.0 
ee-bin ,版本 1.4.0 
ee-core,版本 2.9.1 
better-sqlite3,版本 v8.7.0

此次新增
pyenv ,管理python版本,当前选择 python 2.7.8 (本机还安装有python 3.12.2)
node-hid ,版本 3.0.0

官网参考

node-hid

日志效果截图

实现步骤

vue页面

只截取关键部分

<script setup>

import { ipcApiRoute } from '@/api/main';

import { ipc } from '@/utils/ipcRenderer';

import { toRaw, onMounted, ref, reactive } from 'vue';

const HID = require('node-hid');

const defaultDeviceName = ref('')

const usbList = ref([]);



const chooseDevice = reactive({

data:

{

"interface": 1,

"manufacturer": "i22222",

"path": "DevSrvsID:222",

"product": "keyboard",

"productId": 222,

"release": 8192,

"serialNumber": "233333",

"usagePage": 2,

"vendorId": 3

}

});

onMounted(() => {

init();

})

  


const init = () => {

// 避免重复监听,或者将 on 功能写到一个统一的地方,只加载一次

ipc.removeAllListeners(ipcApiRoute.usbReciveData);

ipc.on(ipcApiRoute.usbReciveData, (event, result) => {

console.log('usbReciveData', result);

})

ipc.removeAllListeners(ipcApiRoute.usbOnerror);

ipc.on(ipcApiRoute.usbOnerror, (event, result) => {

console.log('usbOnerror', result);

})

}

const clearUsbhidHard = () => {

chooseDevice.data = {};

usbList.value = [];

}

const getUsbhidHard = () => {

ipc.invoke(ipcApiRoute.getUsbhidDeviceList, {}).then(res => {

usbList.value = res;

console.log('result', res);

if (res.length > 0) {

chooseDevice.data = { ...res[0] }

}

})

}


const openDevice = () => {

const params = {

productId: chooseDevice.data.productId,

vendorId: chooseDevice.data.vendorId,

}

ipc.send(ipcApiRoute.openDeviceByIds, params)

}

const closeDevice = () => {

ipc.invoke(ipcApiRoute.closeUsbDevice, {}).then(res => {

console.log('关闭', res);

})

}

const sendToDevice = () => {

ipc.invoke(ipcApiRoute.sendDataToUsb, { data: null }).then(res => {

console.log('发送数据', res);

})

}

</script>

controll部分

路径: electron/controller/usbhidHardware.js

'use strict';  


const { Controller } = require('ee-core');

const path = require('path');

const Ps = require('ee-core/ps');

const CoreWindow = require('ee-core/electron/window');

const Addon = require('ee-core/addon');

const HID = require('node-hid');

const Log = require('ee-core/log');

var os = require('os');

const Services = require('ee-core/services');

/**

* 硬件设备 - usbhid通讯

* @class

*/

class UsbhidHardwareController extends Controller {

  


constructor(ctx) {

super(ctx);

this.device = null;

}

  


/**

* 获取Usb列表

* @param {*} args = {name}

* @returns list

*/

getUsbhidDeviceList() {

//主线程获取usb列表

const list = HID.devices();

return list;

}

/**

* 根据productId, vendorId打开设备,

* @param {*} args = { productId, vendorId }

* @returns deviceHandle

*/

async openDeviceByIds(args, event) {

try {

//this.closeUsbDevice();

Log.info('openDeviceByIds args', args)

const { productId, vendorId } = args;

// const device = new HID.HID(vendorId, productId);

this.device = await HID.HIDAsync.open(vendorId, productId);

Log.info("打开设备的句柄, handler");

Log.info(this.device);

Log.info("Attaching receive 'data' handler");

if (!this.device) {

Log.info("打开失败");

return false;

} else {

Log.info("打开成功");

Log.info(await this.device.getDeviceInfo());

}

this.device.on('data', function (data) {

try {

if (data, event) {

const stringRecv = data.toString('hex');

Log.info("==111==== Got data:", stringRecv);

// Log.info(event)

const channel = 'controller.usbhidHardware.usbReciveData';

Log.info("==222====" + channel)

event.reply(`${channel}`, { data: stringRecv });

}

} catch (error) {

Log.error("error:", error);

}

  


});

  


this.device.on('error', function (err) {

try {

Log.error("error:", err);

const channel = 'controller.usbhidHardware.usbOnerror';

if (event) {

Log.info("==222====" + channel)

event.reply(`${channel}`, { data: err });

}

this.device.close()

} catch (error) {

  


}

});

return true;

} catch (error) {

Log.error("error:", error);

}

}

sendDataToUsb(args, event) {

try {

Log.info('sendDataToUsb args', args)

const { data } = args;

if (this.device) {

const buf = [];

buf[0] = 0x0A; //report id

buf[1] = 4; //bytes, data length (包括自己)

buf[2] = 0xA0;// dongle to pc data.

buf[3] = 0; //

buf[4] = 0; //

  


Log.info('Sending message B: ', JSON.stringify(buf))

// write output report with report id 0x0A

const numsentB = this.device.write(buf);

Log.info('messageB len:', buf.length, 'actual sent len:', numsentB);

return true;

}

return false;

} catch (error) {

Log.error("error:", error);

return false;

}

  


}

  


closeUsbDevice(args, event) {

try {

Log.info('closeUsbDevice args', args)

if (this.device) {

this.device.close();

// this.device = null;

return true;

}

return false;

} catch (error) {

Log.error("error:", error);

return false;

}

}

}

  


UsbhidHardwareController.toString = () => '[class UsbhidHardwareController]';

module.exports = UsbhidHardwareController;

service部分

路径: electron/service/usbhidHardware.js

'use strict';
const { Service } = require('ee-core');

/**

* hardware(service层为单例)

* @class

*/

class UsbhidHardwareService extends Service {

constructor(ctx) {

super(ctx);

} 

isTeensy(d, args) {

const { productId, vendorId } = args;

return d.vendorId === vendorId && d.productId === productId;

}

isRawHidUsage(d, args) {

const { usagePage, usage } = args;

return (d.usagePage === usagePage && d.usage === usage);

}


} 


UsbhidHardwareService.toString = () => '[class UsbhidHardwareService]';

module.exports = UsbhidHardwareService;

main.js映射部分

getUsbhidDeviceList: 'controller.usbhidHardware.getUsbhidDeviceList',

openDeviceByIds: 'controller.usbhidHardware.openDeviceByIds',

usbReciveData: 'controller.usbhidHardware.usbReciveData',

usbOnerror: 'controller.usbhidHardware.usbOnerror',

closeUsbDevice: 'controller.usbhidHardware.closeUsbDevice',

sendDataToUsb: 'controller.usbhidHardware.sendDataToUsb',

遗留问题

现在会出现 应用程序退出不了,需要强制退出的情况。device.close()貌似退出不了。 有时候出现设备连接不了的情况,需要插拔设备并重启开关。 哪位伙伴知晓问题的话,拜托回来指点指点我呗。

参考文章

electron和无线鼠标通信代码 - 追逐繁星的孩子的文章 - 知乎 zhuanlan.zhihu.com/p/633818295