daShangDao_newAdmin/node_modules/escpos-usb/index.js
2025-06-05 10:35:45 +08:00

193 lines
4.6 KiB
JavaScript

'use strict';
const os = require('os');
const util = require('util');
const EventEmitter = require('events');
let usb = null;
/**
* [USB Class Codes ]
* @type {Object}
* @docs http://www.usb.org/developers/defined_class
*/
const IFACE_CLASS = {
AUDIO : 0x01,
HID : 0x03,
PRINTER: 0x07,
HUB : 0x09
};
/**
* [function USB]
* @param {[type]} vid [description]
* @param {[type]} pid [description]
* @return {[type]} [description]
*/
function USB(vid, pid){
if (!usb) {
usb = require('usb');
}
EventEmitter.call(this);
var self = this;
this.device = null;
if(vid && pid){
this.device = usb.findByIds(vid, pid);
}else if(vid){
// Set spesific USB device from devices array as coming from USB.findPrinter() function.
// for example
// let devices = escpos.USB.findPrinter();
// => devices [ Device1, Device2 ];
// And Then
// const device = new escpos.USB(Device1); OR device = new escpos.USB(Device2);
this.device = vid;
}else{
var devices = USB.findPrinter();
if(devices && devices.length)
this.device = devices[0];
}
if (!this.device)
throw new Error('Can not find printer');
usb.on('detach', function(device){
if(device == self.device) {
self.emit('detach' , device);
self.emit('disconnect', device);
self.device = null;
}
});
return this;
};
/**
* [findPrinter description]
* @return {[type]} [description]
*/
USB.findPrinter = function(){
if (!usb) {
usb = require('usb');
}
return usb.getDeviceList().filter(function(device){
try{
return device.configDescriptor.interfaces.filter(function(iface){
return iface.filter(function(conf){
return conf.bInterfaceClass === IFACE_CLASS.PRINTER;
}).length;
}).length;
}catch(e){
// console.warn(e)
return false;
}
});
};
/**
* getDevice
*/
USB.getDevice = function(vid, pid){
return new Promise((resolve, reject) => {
const device = new USB(vid, pid);
device.open(err => {
if(err) return reject(err);
resolve(device);
});
});
};
/**
* make USB extends EventEmitter
*/
util.inherits(USB, EventEmitter);
/**
* [open usb device]
* @param {Function} callback [description]
* @return {[type]} [description]
*/
USB.prototype.open = function (callback){
let self = this, counter = 0, index = 0;
this.device.open();
this.device.interfaces.forEach(function(iface){
(function(iface){
iface.setAltSetting(iface.altSetting, function(){
try {
// http://libusb.sourceforge.net/api-1.0/group__dev.html#gab14d11ed6eac7519bb94795659d2c971
// libusb_kernel_driver_active / libusb_attach_kernel_driver / libusb_detach_kernel_driver : "This functionality is not available on Windows."
if ("win32" !== os.platform()) {
if(iface.isKernelDriverActive()) {
try {
iface.detachKernelDriver();
} catch(e) {
console.error("[ERROR] Could not detatch kernel driver: %s", e)
}
}
}
iface.claim(); // must be called before using any endpoints of this interface.
iface.endpoints.filter(function(endpoint){
if(endpoint.direction == 'out' && !self.endpoint) {
self.endpoint = endpoint;
}
});
if(self.endpoint) {
self.emit('connect', self.device);
callback && callback(null, self);
} else if(++counter === this.device.interfaces.length && !self.endpoint){
callback && callback(new Error('Can not find endpoint from printer'));
}
} catch (e) {
// Try/Catch block to prevent process from exit due to uncaught exception.
// i.e LIBUSB_ERROR_ACCESS might be thrown by claim() if USB device is taken by another process
// example: MacOS Parallels
callback && callback(e);
}
});
})(iface);
});
return this;
};
/**
* [function write]
* @param {[type]} data [description]
* @return {[type]} [description]
*/
USB.prototype.write = function(data, callback){
this.emit('data', data);
this.endpoint.transfer(data, callback);
return this;
};
USB.prototype.close = function(callback){
if(this.device) {
try {
this.device.close();
usb.removeAllListeners('detach');
callback && callback(null);
this.emit('close', this.device);
}
catch (e) {
callback && callback(e);
}
}
else {
callback && callback(null);
}
return this;
};
/**
* [exports description]
* @type {[type]}
*/
module.exports = USB;