Skip to content
Tres Finocchiaro edited this page Apr 26, 2021 · 5 revisions

Compatibility

  • ✅ 2.0 | ⛔ 1.9 | ...

Objective

Use QZ Tray to read raw data from an attached USB Device.

Note: Many devices utilize HID, which is easier to use and support.

MacOS Support

Read Data

// Hardware info (modify to match hardware)
var usb = {
   vendor: '0x0EB8',
   product: '0xF000',
   interface: '0x00',
   endpoint: '0x81'
};

// Generic error handler
var err = function(e) { console.error(e); }

// Generic data handler
var process = function(data) { console.log(data); }

// Handler to release claimed device	
var release = function() {
   qz.usb.releaseDevice(usb.vendor, usb.product).catch(err);
}

// Connect to QZ Tray, claim, read, release
qz.websocket.connect().then(function() {
   return qz.usb.claimDevice(usb.vendor, usb.product, usb.interface);
}).then(function() {
   return qz.usb.readData(usb.vendor, usb.product, usb.endpoint, '8'); // *
}).then(process).then(release).catch(err);

// Note:  Some hardware such as Fairbanks scales use '6' for byte length.  Adjust as needed

Send Data

function sendUsbData() {
    qz.usb.sendData('0x0EB8', '0xF000', '0x81', data).catch(displayError);
}

qz.print(config, data).catch(function(e) { console.error(e); });

Process Data

USB Scale

  • Parses data returned from USB port to determine status, weight, units and precision. Compatible with most USB attached scales (Stamps.com, Mettler Toledo, Dymo, etc).
  • Requires read data example above.
var process = function(data) {
   	// Filter erroneous data
        if (data.length < 4 || data.slice(2, 8).join('') == "000000000000") {
            return null;
        }
	// Get status
	var status = parseInt(data[1], 16);
	switch(status) {
		case 1: // fault
		case 5: // underweight
		case 6: // overweight
		case 7: // calibrate
		case 8: // re-zero
			status = 'Error';
			break;
		case 3: // busy
			status = 'Busy';
			break;
		case 2: // stable at zero
		case 4: // stable non-zero
		default:
			status = 'Stable';
	}
	// Get precision
	var precision = parseInt(data[3], 16);
	precision = precision ^ -256; //unsigned to signed
	// xor on 0 causes issues
	if (precision == -256) { precision = 0; }
	// Get units
	var units = parseInt(data[2], 16);
	switch(units) {
		case 2:
			units = 'g';
			break;
		case 3:
			units = 'kg';
			break;
		case 11:
			units = 'oz';
			break;
		case 12:
		default:
			units = 'lbs';
	}
	// Get weight
	data.splice(0, 4);
	data.reverse();
	var weight = parseInt(data.join(''), 16);
	weight *= Math.pow(10, precision);
	weight = weight.toFixed(Math.abs(precision));

	// Log data to the console
	console.log(weight + units + ' - ' + status);
}

Advanced

Get nth

Although not advised for selecting a device, it is often useful to selecting the nth interface or the nth endpoint for a particular device. For example, rather than hard-coding endpoint = '0x81' into the code, endpoint = endpoints[0] may be desired instead.

// Generic error handler
var err = function(e) { console.error(e); }

// Generic data handler
var process = function(data) { console.log(data); }

// Stores device information
var usb = { vendor: null, product: null, interface: null, endpoint: null };

qz.websocket.connect().then(function() {

   // First device
   return qz.usb.listDevices(false);
}).then(function(devices) {
   usb.vendor = "0x" + devices[0].vendorId;
   usb.product = "0x" + devices[0].productId;

   // First interface
   return qz.usb.listInterfaces(usb.vendor, usb.product);
}).then(function(interfaces) {
   usb.interface = "0x" + interfaces[0];

   // First endpoint
   return qz.usb.listEndpoints(usb.vendor, usb.product, usb.interface);
}).then(function(endpoints) {
   usb.endpoint= "0x" + endpoints[0];
   return qz.usb.claimDevice(usb.vendor, usb.product, usb.interface);

  // process, release, err
}).then(function() {
   return qz.usb.readData(usb.vendor, usb.product, usb.endpoint, '8');
}).then(process).then(release).catch(err);
Clone this wiki locally