Skip to content

Instantly share code, notes, and snippets.

@agritheory
Created December 13, 2018 12:06
Show Gist options
  • Save agritheory/a3119dd877476de5fefb6c7ac9e78946 to your computer and use it in GitHub Desktop.
Save agritheory/a3119dd877476de5fefb6c7ac9e78946 to your computer and use it in GitHub Desktop.
HID_scanner.js
// USB Event Detection
const usbDetect = require('usb-detection');
// USB HID library used to interface with USB devices
const HID = require('node-hid');
class Scanner {
constructor(config, socket) {
this.socket = socket;
this.device = null;
this.config = config.get('scanner');
this.station = '';
this.scannerRequired = true;
this.scanAvailable = false;
/**
* Map for converting bar code ints to proper characters
*/
this.hidMap = {
4: "A", 5: "B", 6: "C", 7: "D", 8: "E",
9: "F", 10: "G", 11: "H", 12: "I", 13: "J",
14: "K", 15: "L", 16: "M", 17: "N", 18: "O",
19: "P", 20: "Q", 21: "R", 22: "S", 23: "T",
24: "U", 25: "V", 26: "W", 27: "X", 28: "Y",
29: "Z", 30: '1', 31: '2', 32: '3', 33: '4',
34: '5', 35: '6', 36: '7', 37: '8', 38: '9',
// enter - barcode escape char
39: '0', 40: 'enter', 44: " ", 45: "-", 55: ".", 56: "/",
85: "*", 87: "+"
};
}
/**
* Find the device we are expecting. If found attach and start listening.
*/
findDevice() {
const self = this;
// Check for existing device
if (this.device) {
return;
}
// Find and attach
usbDetect.find(self.config.vendorId, self.config.productId, function (err, devices) {
}).then(function (devices) {
if ((devices.length > 0)) {
self.attach(devices[0]);
} else {
// Send status message
self.sendScannerStatus();
}
});
}
/**
* Attach the passed device for scanning
*
* @param device
*/
attach(device) {
this.device = new HID.HID(device.vendorId, device.productId);
this.scanAvailable = true;
const hidMap = this.hidMap;
// empty array for barcode bytes
let bcodeBuff = [];
// string variable to hold barcode string
let barCode = "";
const self = this;
// When device receives a chunk of data from scanning handle it
this.device.on("data", function (chunk) {
// Second byte of buffer is all that contains data
if (hidMap[chunk[2]]) {
// Escape character (enter)
if (chunk[2] === 40) {
barCode = bcodeBuff.join("");
bcodeBuff = [];
// Send code scan
self.scanned(barCode);
} else {
// Add converted chunk
bcodeBuff.push(hidMap[chunk[2]]);
}
}
});
// Bind to device error, usually due to disconnected device (unplug)
this.device.on('error', function (err) {
console.error('Caught Device Error!', err, ". This is usually caused by unplugging the device being used.");
});
// Send status message
this.sendScannerStatus();
}
/**
* Attached device has been detached (unplugged)
*/
detached() {
this.device.close();
this.device = null;
this.scanAvailable = false;
// Send status message
this.sendScannerStatus();
}
/**
* Handle code scan
*
* @param code
*/
scanned(code) {
console.debug('Scanned code:', code);
// Check make sure we have something defined so we can offload
if (typeof this.station.handleScan === 'function') {
// Handle the scanned code
this.station.handleScan(code);
}
}
/**
* Reset material creation station
*
* @param code
*/
resetStation() {
// Check make sure we have something defined so we can offload
if (typeof this.station.reset === 'function') {
// Reset station
this.station.reset();
}
}
/**
* Listen for USB device changes related to the defined scanner
*/
deviceListeners() {
const self = this;
// Listen for attach
usbDetect.on('add:' + this.config.vendorId + ':' + this.config.productId, function (device) {
console.log('Device added', device);
self.findDevice(device);
});
// Listen for detach
usbDetect.on('remove:' + this.config.vendorId + ':' + this.config.productId, function (device) {
console.log('Device removed', device);
self.detached();
});
}
/**
* Send the scanner status as a socket event
*/
sendScannerStatus() {
let enabled = (this.device) ? true : false;
this.socket.sendScannerStatus(enabled, this.scannerRequired);
}
}
module.exports = Scanner;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment